LCOV - code coverage report
Current view: top level - dev/pci - ixgbe_x550.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1000 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 59 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ixgbe_x550.c,v 1.4 2016/12/06 16:21:20 mikeb Exp $    */
       2             : 
       3             : /******************************************************************************
       4             : 
       5             :   Copyright (c) 2001-2015, Intel Corporation
       6             :   All rights reserved.
       7             : 
       8             :   Redistribution and use in source and binary forms, with or without
       9             :   modification, are permitted provided that the following conditions are met:
      10             : 
      11             :    1. Redistributions of source code must retain the above copyright notice,
      12             :       this list of conditions and the following disclaimer.
      13             : 
      14             :    2. Redistributions in binary form must reproduce the above copyright
      15             :       notice, this list of conditions and the following disclaimer in the
      16             :       documentation and/or other materials provided with the distribution.
      17             : 
      18             :    3. Neither the name of the Intel Corporation nor the names of its
      19             :       contributors may be used to endorse or promote products derived from
      20             :       this software without specific prior written permission.
      21             : 
      22             :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      23             :   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24             :   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25             :   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      26             :   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      27             :   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      28             :   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29             :   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      30             :   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      31             :   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      32             :   POSSIBILITY OF SUCH DAMAGE.
      33             : 
      34             : ******************************************************************************/
      35             : /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.c 295093 2016-01-31 15:14:23Z smh $*/
      36             : 
      37             : #include <dev/pci/ixgbe.h>
      38             : #include <dev/pci/ixgbe_type.h>
      39             : 
      40             : extern int32_t ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw);
      41             : extern int32_t ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, uint32_t mask);
      42             : extern void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, uint32_t mask);
      43             : 
      44             : int32_t ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw);
      45             : int32_t ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw);
      46             : int32_t ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw);
      47             : int32_t ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw);
      48             : int32_t ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, uint16_t *buffer,
      49             :                                  uint32_t buffer_size);
      50             : int32_t ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
      51             :                                             uint16_t *checksum_val);
      52             : int32_t ixgbe_update_flash_X550(struct ixgbe_hw *hw);
      53             : int32_t ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset,
      54             :                                uint16_t data);
      55             : int32_t ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
      56             :                                          uint16_t offset, uint16_t words,
      57             :                                          uint16_t *data);
      58             : int32_t ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset,
      59             :                                   uint16_t *data);
      60             : int32_t ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset,
      61             :                                        uint16_t *data);
      62             : int32_t ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset,
      63             :                                         uint16_t data);
      64             : int32_t ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr,
      65             :                                      uint32_t device_type, uint32_t data);
      66             : int32_t ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr,
      67             :                                     uint32_t device_type, uint32_t *data);
      68             : enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw);
      69             : int32_t ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw);
      70             : int32_t ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
      71             :                                            ixgbe_link_speed *speed,
      72             :                                            bool *autoneg);
      73             : void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw);
      74             : int32_t ixgbe_reset_hw_X550em(struct ixgbe_hw *hw);
      75             : int32_t ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw);
      76             : int32_t ixgbe_setup_kr_x550em(struct ixgbe_hw *hw);
      77             : int32_t ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw);
      78             : int32_t ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw);
      79             : int32_t ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw);
      80             : uint32_t ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw);
      81             : void ixgbe_disable_rx_x550(struct ixgbe_hw *hw);
      82             : int32_t ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed);
      83             : int32_t ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask);
      84             : void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask);
      85             : int32_t ixgbe_setup_fc_X550em(struct ixgbe_hw *hw);
      86             : int32_t ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
      87             :                                         ixgbe_link_speed speed,
      88             :                                         bool autoneg_wait_to_complete);
      89             : int32_t ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw);
      90             : int32_t ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
      91             :                                       ixgbe_link_speed speed,
      92             :                                       bool autoneg_wait_to_complete);
      93             : int32_t ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
      94             :                                   bool *link_up, bool link_up_wait_to_complete);
      95             : int32_t ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw);
      96             : int32_t ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw);
      97             : int32_t ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx);
      98             : int32_t ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx);
      99             : 
     100             : int32_t ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
     101             : 
     102             : /**
     103             :  *  ixgbe_init_ops_X550 - Inits func ptrs and MAC type
     104             :  *  @hw: pointer to hardware structure
     105             :  *
     106             :  *  Initialize the function pointers and assign the MAC type for X550.
     107             :  *  Does not touch the hardware.
     108             :  **/
     109           0 : int32_t ixgbe_init_ops_X550(struct ixgbe_hw *hw)
     110             : {
     111           0 :         struct ixgbe_mac_info *mac = &hw->mac;
     112           0 :         struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
     113             :         int32_t ret_val;
     114             : 
     115             :         DEBUGFUNC("ixgbe_init_ops_X550");
     116             : 
     117           0 :         ret_val = ixgbe_init_ops_X540(hw);
     118             : 
     119           0 :         eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
     120           0 :         eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
     121           0 :         eeprom->ops.read = ixgbe_read_ee_hostif_X550;
     122           0 :         eeprom->ops.write = ixgbe_write_ee_hostif_X550;
     123           0 :         eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
     124           0 :         eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
     125             : 
     126           0 :         mac->ops.disable_rx = ixgbe_disable_rx_x550;
     127           0 :         if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
     128           0 :                 hw->mac.ops.led_on = ixgbe_led_on_t_X550em;
     129           0 :                 hw->mac.ops.led_off = ixgbe_led_off_t_X550em;
     130           0 :         }
     131           0 :         return ret_val;
     132             : }
     133             : 
     134             : /**
     135             :  * ixgbe_read_cs4227 - Read CS4227 register
     136             :  * @hw: pointer to hardware structure
     137             :  * @reg: register number to write
     138             :  * @value: pointer to receive value read
     139             :  *
     140             :  * Returns status code
     141             :  **/
     142           0 : int32_t ixgbe_read_cs4227(struct ixgbe_hw *hw, uint16_t reg, uint16_t *value)
     143             : {
     144           0 :         return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
     145             :                                                       value);
     146             : }
     147             : 
     148             : /**
     149             :  * ixgbe_write_cs4227 - Write CS4227 register
     150             :  * @hw: pointer to hardware structure
     151             :  * @reg: register number to write
     152             :  * @value: value to write to register
     153             :  *
     154             :  * Returns status code
     155             :  **/
     156           0 : int32_t ixgbe_write_cs4227(struct ixgbe_hw *hw, uint16_t reg, uint16_t value)
     157             : {
     158           0 :         return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
     159             :                                                        value);
     160             : }
     161             : 
     162             : /**
     163             :  * ixgbe_read_pe - Read register from port expander
     164             :  * @hw: pointer to hardware structure
     165             :  * @reg: register number to read
     166             :  * @value: pointer to receive read value
     167             :  *
     168             :  * Returns status code
     169             :  **/
     170           0 : int32_t ixgbe_read_pe(struct ixgbe_hw *hw, uint8_t reg, uint8_t *value)
     171             : {
     172             :         int32_t status;
     173             : 
     174           0 :         status = hw->phy.ops.read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
     175             :         if (status != IXGBE_SUCCESS)
     176             :                 DEBUGOUT1("port expander access failed with %d\n", status);
     177           0 :         return status;
     178             : }
     179             : 
     180             : /**
     181             :  * ixgbe_write_pe - Write register to port expander
     182             :  * @hw: pointer to hardware structure
     183             :  * @reg: register number to write
     184             :  * @value: value to write
     185             :  *
     186             :  * Returns status code
     187             :  **/
     188           0 : int32_t ixgbe_write_pe(struct ixgbe_hw *hw, uint8_t reg, uint8_t value)
     189             : {
     190             :         int32_t status;
     191             : 
     192           0 :         status = hw->phy.ops.write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value);
     193             :         if (status != IXGBE_SUCCESS)
     194             :                 DEBUGOUT1("port expander access failed with %d\n", status);
     195           0 :         return status;
     196             : }
     197             : 
     198             : /**
     199             :  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
     200             :  * @hw: pointer to hardware structure
     201             :  *
     202             :  * This function assumes that the caller has acquired the proper semaphore.
     203             :  * Returns error code
     204             :  **/
     205           0 : int32_t ixgbe_reset_cs4227(struct ixgbe_hw *hw)
     206             : {
     207             :         int32_t status;
     208             :         uint32_t retry;
     209           0 :         uint16_t value;
     210           0 :         uint8_t reg;
     211             : 
     212             :         /* Trigger hard reset. */
     213           0 :         status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
     214           0 :         if (status != IXGBE_SUCCESS)
     215           0 :                 return status;
     216           0 :         reg |= IXGBE_PE_BIT1;
     217           0 :         status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
     218           0 :         if (status != IXGBE_SUCCESS)
     219           0 :                 return status;
     220             : 
     221           0 :         status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, &reg);
     222           0 :         if (status != IXGBE_SUCCESS)
     223           0 :                 return status;
     224           0 :         reg &= ~IXGBE_PE_BIT1;
     225           0 :         status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg);
     226           0 :         if (status != IXGBE_SUCCESS)
     227           0 :                 return status;
     228             : 
     229           0 :         status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
     230           0 :         if (status != IXGBE_SUCCESS)
     231           0 :                 return status;
     232           0 :         reg &= ~IXGBE_PE_BIT1;
     233           0 :         status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
     234           0 :         if (status != IXGBE_SUCCESS)
     235           0 :                 return status;
     236             : 
     237           0 :         usec_delay(IXGBE_CS4227_RESET_HOLD);
     238             : 
     239           0 :         status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
     240           0 :         if (status != IXGBE_SUCCESS)
     241           0 :                 return status;
     242           0 :         reg |= IXGBE_PE_BIT1;
     243           0 :         status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg);
     244           0 :         if (status != IXGBE_SUCCESS)
     245           0 :                 return status;
     246             : 
     247             :         /* Wait for the reset to complete. */
     248           0 :         msec_delay(IXGBE_CS4227_RESET_DELAY);
     249           0 :         for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
     250           0 :                 status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
     251             :                                            &value);
     252           0 :                 if (status == IXGBE_SUCCESS &&
     253           0 :                     value == IXGBE_CS4227_EEPROM_LOAD_OK)
     254             :                         break;
     255           0 :                 msec_delay(IXGBE_CS4227_CHECK_DELAY);
     256             :         }
     257           0 :         if (retry == IXGBE_CS4227_RETRIES) {
     258             :                 DEBUGOUT("CS4227 reset did not complete.\n");
     259           0 :                 return IXGBE_ERR_PHY;
     260             :         }
     261             : 
     262           0 :         status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
     263           0 :         if (status != IXGBE_SUCCESS ||
     264           0 :             !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
     265             :                 DEBUGOUT("CS4227 EEPROM did not load successfully.\n");
     266           0 :                 return IXGBE_ERR_PHY;
     267             :         }
     268             : 
     269           0 :         return IXGBE_SUCCESS;
     270           0 : }
     271             : 
     272             : /**
     273             :  * ixgbe_check_cs4227 - Check CS4227 and reset as needed
     274             :  * @hw: pointer to hardware structure
     275             :  **/
     276           0 : void ixgbe_check_cs4227(struct ixgbe_hw *hw)
     277             : {
     278             :         int32_t status = IXGBE_SUCCESS;
     279           0 :         uint32_t swfw_mask = hw->phy.phy_semaphore_mask;
     280           0 :         uint16_t value = 0;
     281             :         uint8_t retry;
     282             : 
     283           0 :         for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
     284           0 :                 status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
     285           0 :                 if (status != IXGBE_SUCCESS) {
     286             :                         DEBUGOUT1("semaphore failed with %d\n", status);
     287           0 :                         msec_delay(IXGBE_CS4227_CHECK_DELAY);
     288           0 :                         continue;
     289             :                 }
     290             : 
     291             :                 /* Get status of reset flow. */
     292           0 :                 status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
     293             : 
     294           0 :                 if (status == IXGBE_SUCCESS &&
     295           0 :                     value == IXGBE_CS4227_RESET_COMPLETE)
     296             :                         goto out;
     297             : 
     298           0 :                 if (status != IXGBE_SUCCESS ||
     299           0 :                     value != IXGBE_CS4227_RESET_PENDING)
     300             :                         break;
     301             : 
     302             :                 /* Reset is pending. Wait and check again. */
     303           0 :                 hw->mac.ops.release_swfw_sync(hw, swfw_mask);
     304           0 :                 msec_delay(IXGBE_CS4227_CHECK_DELAY);
     305           0 :         }
     306             : 
     307             :         /* If still pending, assume other instance failed. */
     308           0 :         if (retry == IXGBE_CS4227_RETRIES) {
     309           0 :                 status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
     310           0 :                 if (status != IXGBE_SUCCESS) {
     311             :                         DEBUGOUT1("semaphore failed with %d\n", status);
     312           0 :                         return;
     313             :                 }
     314             :         }
     315             : 
     316             :         /* Reset the CS4227. */
     317           0 :         status = ixgbe_reset_cs4227(hw);
     318           0 :         if (status != IXGBE_SUCCESS) {
     319             :                 DEBUGOUT1("CS4227 reset failed: %d\n", status);
     320             :                 goto out;
     321             :         }
     322             : 
     323             :         /* Reset takes so long, temporarily release semaphore in case the
     324             :          * other driver instance is waiting for the reset indication.
     325             :          */
     326           0 :         ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
     327             :                            IXGBE_CS4227_RESET_PENDING);
     328           0 :         hw->mac.ops.release_swfw_sync(hw, swfw_mask);
     329           0 :         msec_delay(10);
     330           0 :         status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
     331           0 :         if (status != IXGBE_SUCCESS) {
     332             :                 DEBUGOUT1("semaphore failed with %d\n", status);
     333           0 :                 return;
     334             :         }
     335             : 
     336             :         /* Record completion for next time. */
     337           0 :         status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
     338             :                 IXGBE_CS4227_RESET_COMPLETE);
     339             : 
     340             : out:
     341           0 :         hw->mac.ops.release_swfw_sync(hw, swfw_mask);
     342           0 :         msec_delay(hw->eeprom.semaphore_delay);
     343           0 : }
     344             : 
     345             : /**
     346             :  * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
     347             :  * @hw: pointer to hardware structure
     348             :  **/
     349           0 : void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
     350             : {
     351           0 :         uint32_t esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
     352             : 
     353           0 :         if (hw->bus.lan_id) {
     354           0 :                 esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
     355           0 :                 esdp |= IXGBE_ESDP_SDP1_DIR;
     356           0 :         }
     357           0 :         esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
     358           0 :         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
     359           0 :         IXGBE_WRITE_FLUSH(hw);
     360           0 : }
     361             : 
     362             : /**
     363             :  * ixgbe_identify_phy_x550em - Get PHY type based on device id
     364             :  * @hw: pointer to hardware structure
     365             :  *
     366             :  * Returns error code
     367             :  */
     368           0 : int32_t ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
     369             : {
     370             :         int32_t ret_val;
     371             : 
     372           0 :         switch (hw->device_id) {
     373             :         case IXGBE_DEV_ID_X550EM_X_SFP:
     374             :                 /* set up for CS4227 usage */
     375           0 :                 hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
     376           0 :                 ixgbe_setup_mux_ctl(hw);
     377           0 :                 ixgbe_check_cs4227(hw);
     378             : 
     379           0 :                 ret_val = ixgbe_identify_module_generic(hw);
     380             : 
     381             :                 /* Set PHY type none if no SFP detected */
     382           0 :                 if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) {
     383           0 :                         hw->phy.type = ixgbe_phy_none;
     384           0 :                         return IXGBE_SUCCESS;
     385             :                 }
     386           0 :                 return ret_val;
     387             :                 break;
     388             :         case IXGBE_DEV_ID_X550EM_X_KX4:
     389           0 :                 hw->phy.type = ixgbe_phy_x550em_kx4;
     390           0 :                 break;
     391             :         case IXGBE_DEV_ID_X550EM_X_KR:
     392           0 :                 hw->phy.type = ixgbe_phy_x550em_kr;
     393           0 :                 break;
     394             :         case IXGBE_DEV_ID_X550EM_X_1G_T:
     395             :         case IXGBE_DEV_ID_X550EM_X_10G_T:
     396           0 :                 return ixgbe_identify_phy_generic(hw);
     397             :         default:
     398             :                 break;
     399             :         }
     400           0 :         return IXGBE_SUCCESS;
     401           0 : }
     402             : 
     403           0 : int32_t ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, uint32_t reg_addr,
     404             :                                   uint32_t device_type, uint16_t *phy_data)
     405             : {
     406           0 :         return IXGBE_NOT_IMPLEMENTED;
     407             : }
     408             : 
     409           0 : int32_t ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, uint32_t reg_addr,
     410             :                                    uint32_t device_type, uint16_t phy_data)
     411             : {
     412           0 :         return IXGBE_NOT_IMPLEMENTED;
     413             : }
     414             : 
     415             : /**
     416             : *  ixgbe_init_ops_X550EM - Inits func ptrs and MAC type
     417             : *  @hw: pointer to hardware structure
     418             : *
     419             : *  Initialize the function pointers and for MAC type X550EM.
     420             : *  Does not touch the hardware.
     421             : **/
     422           0 : int32_t ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
     423             : {
     424           0 :         struct ixgbe_mac_info *mac = &hw->mac;
     425           0 :         struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
     426           0 :         struct ixgbe_phy_info *phy = &hw->phy;
     427             :         int32_t ret_val;
     428             : 
     429             :         DEBUGFUNC("ixgbe_init_ops_X550EM");
     430             : 
     431             :         /* Similar to X550 so start there. */
     432           0 :         ret_val = ixgbe_init_ops_X550(hw);
     433             : 
     434             :         /* Since this function eventually calls
     435             :          * ixgbe_init_ops_540 by design, we are setting
     436             :          * the pointers to NULL explicitly here to overwrite
     437             :          * the values being set in the x540 function.
     438             :          */
     439             : 
     440             :         /* IPsec not supported in x550EM */
     441           0 :         mac->ops.disable_sec_rx_path = NULL;
     442           0 :         mac->ops.enable_sec_rx_path = NULL;
     443             : 
     444             :         /* AUTOC register is not present in x550EM. */
     445           0 :         mac->ops.prot_autoc_read = NULL;
     446           0 :         mac->ops.prot_autoc_write = NULL;
     447             : 
     448             :         /* X550EM bus type is internal*/
     449           0 :         hw->bus.type = ixgbe_bus_type_internal;
     450           0 :         mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
     451             : 
     452           0 :         mac->ops.get_media_type = ixgbe_get_media_type_X550em;
     453           0 :         mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
     454           0 :         mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
     455           0 :         mac->ops.reset_hw = ixgbe_reset_hw_X550em;
     456           0 :         mac->ops.get_supported_physical_layer =
     457             :                                     ixgbe_get_supported_physical_layer_X550em;
     458             : 
     459           0 :         if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
     460           0 :                 mac->ops.setup_fc = ixgbe_setup_fc_generic;
     461             :         else
     462           0 :                 mac->ops.setup_fc = ixgbe_setup_fc_X550em;
     463             : 
     464           0 :         mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em;
     465           0 :         mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em;
     466             : 
     467             :         /* PHY */
     468           0 :         phy->ops.init = ixgbe_init_phy_ops_X550em;
     469           0 :         phy->ops.identify = ixgbe_identify_phy_x550em;
     470           0 :         if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
     471           0 :                 phy->ops.set_phy_power = NULL;
     472             : 
     473             : 
     474             :         /* EEPROM */
     475           0 :         eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
     476           0 :         eeprom->ops.read = ixgbe_read_ee_hostif_X550;
     477           0 :         eeprom->ops.write = ixgbe_write_ee_hostif_X550;
     478           0 :         eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
     479           0 :         eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
     480           0 :         eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
     481             : 
     482           0 :         return ret_val;
     483             : }
     484             : 
     485             : /**
     486             :  *  ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
     487             :  *  @hw: pointer to hardware structure
     488             :  *
     489             :  *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
     490             :  *  ixgbe_hw struct in order to set up EEPROM access.
     491             :  **/
     492           0 : int32_t ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
     493             : {
     494           0 :         struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
     495             :         uint32_t eec;
     496             :         uint16_t eeprom_size;
     497             : 
     498             :         DEBUGFUNC("ixgbe_init_eeprom_params_X550");
     499             : 
     500           0 :         if (eeprom->type == ixgbe_eeprom_uninitialized) {
     501           0 :                 eeprom->semaphore_delay = 10;
     502           0 :                 eeprom->type = ixgbe_flash;
     503             : 
     504           0 :                 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
     505           0 :                 eeprom_size = (uint16_t)((eec & IXGBE_EEC_SIZE) >>
     506             :                                     IXGBE_EEC_SIZE_SHIFT);
     507           0 :                 eeprom->word_size = 1 << (eeprom_size +
     508             :                                           IXGBE_EEPROM_WORD_SIZE_SHIFT);
     509             : 
     510             :                 DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
     511             :                           eeprom->type, eeprom->word_size);
     512           0 :         }
     513             : 
     514           0 :         return IXGBE_SUCCESS;
     515             : }
     516             : 
     517             : /**
     518             :  * ixgbe_iosf_wait - Wait for IOSF command completion
     519             :  * @hw: pointer to hardware structure
     520             :  * @ctrl: pointer to location to receive final IOSF control value
     521             :  *
     522             :  * Returns failing status on timeout
     523             :  *
     524             :  * Note: ctrl can be NULL if the IOSF control register value is not needed
     525             :  **/
     526           0 : int32_t ixgbe_iosf_wait(struct ixgbe_hw *hw, uint32_t *ctrl)
     527             : {
     528             :         uint32_t i, command = 0;
     529             : 
     530             :         /* Check every 10 usec to see if the address cycle completed.
     531             :          * The SB IOSF BUSY bit will clear when the operation is
     532             :          * complete
     533             :          */
     534           0 :         for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
     535           0 :                 command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL);
     536           0 :                 if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0)
     537             :                         break;
     538           0 :                 usec_delay(10);
     539             :         }
     540           0 :         if (ctrl)
     541           0 :                 *ctrl = command;
     542           0 :         if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
     543             :                 DEBUGOUT( "Wait timed out\n");
     544           0 :                 return IXGBE_ERR_PHY;
     545             :         }
     546             : 
     547           0 :         return IXGBE_SUCCESS;
     548           0 : }
     549             : 
     550             : /**
     551             :  *  ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the IOSF
     552             :  *  device
     553             :  *  @hw: pointer to hardware structure
     554             :  *  @reg_addr: 32 bit PHY register to write
     555             :  *  @device_type: 3 bit device type
     556             :  *  @data: Data to write to the register
     557             :  **/
     558           0 : int32_t ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr,
     559             :                                      uint32_t device_type, uint32_t data)
     560             : {
     561             :         uint32_t gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
     562           0 :         uint32_t command, error;
     563             :         int32_t ret;
     564             : 
     565           0 :         ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
     566           0 :         if (ret != IXGBE_SUCCESS)
     567           0 :                 return ret;
     568             : 
     569           0 :         ret = ixgbe_iosf_wait(hw, NULL);
     570           0 :         if (ret != IXGBE_SUCCESS)
     571             :                 goto out;
     572             : 
     573           0 :         command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
     574           0 :                    (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
     575             : 
     576             :         /* Write IOSF control register */
     577           0 :         IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
     578             : 
     579             :         /* Write IOSF data register */
     580           0 :         IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data);
     581             : 
     582           0 :         ret = ixgbe_iosf_wait(hw, &command);
     583             : 
     584           0 :         if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
     585           0 :                 error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
     586             :                          IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
     587             :                 DEBUGOUT1("Failed to write, error %x\n", error);
     588             :                 ret = IXGBE_ERR_PHY;
     589           0 :         }
     590             : 
     591             : out:
     592           0 :         hw->mac.ops.release_swfw_sync(hw, gssr);
     593           0 :         return ret;
     594           0 : }
     595             : 
     596             : /**
     597             :  *  ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the IOSF
     598             :  *  device
     599             :  *  @hw: pointer to hardware structure
     600             :  *  @reg_addr: 32 bit PHY register to write
     601             :  *  @device_type: 3 bit device type
     602             :  *  @phy_data: Pointer to read data from the register
     603             :  **/
     604           0 : int32_t ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, uint32_t reg_addr,
     605             :                                     uint32_t device_type, uint32_t *data)
     606             : {
     607             :         uint32_t gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM;
     608           0 :         uint32_t command, error;
     609             :         int32_t ret;
     610             : 
     611           0 :         ret = hw->mac.ops.acquire_swfw_sync(hw, gssr);
     612           0 :         if (ret != IXGBE_SUCCESS)
     613           0 :                 return ret;
     614             : 
     615           0 :         ret = ixgbe_iosf_wait(hw, NULL);
     616           0 :         if (ret != IXGBE_SUCCESS)
     617             :                 goto out;
     618             : 
     619           0 :         command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) |
     620           0 :                    (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT));
     621             : 
     622             :         /* Write IOSF control register */
     623           0 :         IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command);
     624             : 
     625           0 :         ret = ixgbe_iosf_wait(hw, &command);
     626             : 
     627           0 :         if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
     628           0 :                 error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
     629             :                          IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
     630             :                 DEBUGOUT1("Failed to read, error %x\n", error);
     631             :                 ret = IXGBE_ERR_PHY;
     632           0 :         }
     633             : 
     634           0 :         if (ret == IXGBE_SUCCESS)
     635           0 :                 *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA);
     636             : 
     637             : out:
     638           0 :         hw->mac.ops.release_swfw_sync(hw, gssr);
     639           0 :         return ret;
     640           0 : }
     641             : 
     642             : /**
     643             :  *  ixgbe_get_media_type_X550em - Get media type
     644             :  *  @hw: pointer to hardware structure
     645             :  *
     646             :  *  Returns the media type (fiber, copper, backplane)
     647             :  */
     648           0 : enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
     649             : {
     650             :         enum ixgbe_media_type media_type;
     651             : 
     652             :         DEBUGFUNC("ixgbe_get_media_type_X550em");
     653             : 
     654             :         /* Detect if there is a copper PHY attached. */
     655           0 :         switch (hw->device_id) {
     656             :         case IXGBE_DEV_ID_X550EM_X_KR:
     657             :         case IXGBE_DEV_ID_X550EM_X_KX4:
     658             :                 media_type = ixgbe_media_type_backplane;
     659           0 :                 break;
     660             :         case IXGBE_DEV_ID_X550EM_X_SFP:
     661             :                 media_type = ixgbe_media_type_fiber;
     662           0 :                 break;
     663             :         case IXGBE_DEV_ID_X550EM_X_1G_T:
     664             :         case IXGBE_DEV_ID_X550EM_X_10G_T:
     665             :                 media_type = ixgbe_media_type_copper;
     666           0 :                 break;
     667             :         default:
     668             :                 media_type = ixgbe_media_type_unknown;
     669           0 :                 break;
     670             :         }
     671           0 :         return media_type;
     672             : }
     673             : 
     674             : /**
     675             :  *  ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported
     676             :  *  @hw: pointer to hardware structure
     677             :  *  @linear: TRUE if SFP module is linear
     678             :  */
     679           0 : int32_t ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear)
     680             : {
     681             :         DEBUGFUNC("ixgbe_supported_sfp_modules_X550em");
     682             : 
     683           0 :         switch (hw->phy.sfp_type) {
     684             :         case ixgbe_sfp_type_not_present:
     685           0 :                 return IXGBE_ERR_SFP_NOT_PRESENT;
     686             :         case ixgbe_sfp_type_da_cu_core0:
     687             :         case ixgbe_sfp_type_da_cu_core1:
     688           0 :                 *linear = TRUE;
     689           0 :                 break;
     690             :         case ixgbe_sfp_type_srlr_core0:
     691             :         case ixgbe_sfp_type_srlr_core1:
     692             :         case ixgbe_sfp_type_da_act_lmt_core0:
     693             :         case ixgbe_sfp_type_da_act_lmt_core1:
     694             :         case ixgbe_sfp_type_1g_sx_core0:
     695             :         case ixgbe_sfp_type_1g_sx_core1:
     696             :         case ixgbe_sfp_type_1g_lx_core0:
     697             :         case ixgbe_sfp_type_1g_lx_core1:
     698           0 :                 *linear = FALSE;
     699           0 :                 break;
     700             :         case ixgbe_sfp_type_unknown:
     701             :         case ixgbe_sfp_type_1g_cu_core0:
     702             :         case ixgbe_sfp_type_1g_cu_core1:
     703             :         default:
     704           0 :                 return IXGBE_ERR_SFP_NOT_SUPPORTED;
     705             :         }
     706             : 
     707           0 :         return IXGBE_SUCCESS;
     708           0 : }
     709             : 
     710             : /**
     711             :  *  ixgbe_identify_sfp_module_X550em - Identifies SFP modules
     712             :  *  @hw: pointer to hardware structure
     713             :  *
     714             :  *  Searches for and identifies the SFP module and assigns appropriate PHY type.
     715             :  **/
     716           0 : int32_t ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw)
     717             : {
     718             :         int32_t status;
     719           0 :         bool linear;
     720             : 
     721             :         DEBUGFUNC("ixgbe_identify_sfp_module_X550em");
     722             : 
     723           0 :         status = ixgbe_identify_module_generic(hw);
     724             : 
     725           0 :         if (status != IXGBE_SUCCESS)
     726           0 :                 return status;
     727             : 
     728             :         /* Check if SFP module is supported */
     729           0 :         status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
     730             : 
     731           0 :         return status;
     732           0 : }
     733             : 
     734             : /**
     735             :  *  ixgbe_setup_sfp_modules_X550em - Setup MAC link ops
     736             :  *  @hw: pointer to hardware structure
     737             :  */
     738           0 : int32_t ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
     739             : {
     740             :         int32_t status;
     741           0 :         bool linear;
     742             : 
     743             :         DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
     744             : 
     745             :         /* Check if SFP module is supported */
     746           0 :         status = ixgbe_supported_sfp_modules_X550em(hw, &linear);
     747             : 
     748           0 :         if (status != IXGBE_SUCCESS)
     749           0 :                 return status;
     750             : 
     751           0 :         ixgbe_init_mac_link_ops_X550em(hw);
     752           0 :         hw->phy.ops.reset = NULL;
     753             : 
     754           0 :         return IXGBE_SUCCESS;
     755           0 : }
     756             : 
     757             : /**
     758             :  *  ixgbe_init_mac_link_ops_X550em - init mac link function pointers
     759             :  *  @hw: pointer to hardware structure
     760             :  */
     761           0 : void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
     762             : {
     763           0 :         struct ixgbe_mac_info *mac = &hw->mac;
     764             : 
     765             :         DEBUGFUNC("ixgbe_init_mac_link_ops_X550em");
     766             : 
     767           0 :          switch (hw->mac.ops.get_media_type(hw)) {
     768             :          case ixgbe_media_type_fiber:
     769             :                 /* CS4227 does not support autoneg, so disable the laser control
     770             :                  * functions for SFP+ fiber
     771             :                  */
     772           0 :                 mac->ops.disable_tx_laser = NULL;
     773           0 :                 mac->ops.enable_tx_laser = NULL;
     774           0 :                 mac->ops.flap_tx_laser = NULL;
     775           0 :                 mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
     776           0 :                 mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em;
     777           0 :                 mac->ops.set_rate_select_speed =
     778             :                                         ixgbe_set_soft_rate_select_speed;
     779           0 :                 break;
     780             :         case ixgbe_media_type_copper:
     781           0 :                 mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
     782           0 :                 mac->ops.check_link = ixgbe_check_link_t_X550em;
     783           0 :                 break;
     784             :         default:
     785             :                 break;
     786             :          }
     787           0 : }
     788             : 
     789             : /**
     790             :  *  ixgbe_get_link_capabilities_x550em - Determines link capabilities
     791             :  *  @hw: pointer to hardware structure
     792             :  *  @speed: pointer to link speed
     793             :  *  @autoneg: TRUE when autoneg or autotry is enabled
     794             :  */
     795           0 : int32_t ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
     796             :                                            ixgbe_link_speed *speed,
     797             :                                            bool *autoneg)
     798             : {
     799             :         DEBUGFUNC("ixgbe_get_link_capabilities_X550em");
     800             : 
     801             :         /* SFP */
     802           0 :         if (hw->phy.media_type == ixgbe_media_type_fiber) {
     803             : 
     804             :                 /* CS4227 SFP must not enable auto-negotiation */
     805           0 :                 *autoneg = FALSE;
     806             : 
     807             :                 /* Check if 1G SFP module. */
     808           0 :                 if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
     809           0 :                     hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1
     810           0 :                     || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
     811           0 :                     hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
     812           0 :                         *speed = IXGBE_LINK_SPEED_1GB_FULL;
     813           0 :                         return IXGBE_SUCCESS;
     814             :                 }
     815             : 
     816             :                 /* Link capabilities are based on SFP */
     817           0 :                 if (hw->phy.multispeed_fiber)
     818           0 :                         *speed = IXGBE_LINK_SPEED_10GB_FULL |
     819             :                                  IXGBE_LINK_SPEED_1GB_FULL;
     820             :                 else
     821           0 :                         *speed = IXGBE_LINK_SPEED_10GB_FULL;
     822             :         } else {
     823           0 :                 *speed = IXGBE_LINK_SPEED_10GB_FULL |
     824             :                          IXGBE_LINK_SPEED_1GB_FULL;
     825           0 :                 *autoneg = TRUE;
     826             :         }
     827             : 
     828           0 :         return IXGBE_SUCCESS;
     829           0 : }
     830             : 
     831             : /**
     832             :  * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
     833             :  * @hw: pointer to hardware structure
     834             :  * @lsc: pointer to boolean flag which indicates whether external Base T
     835             :  *       PHY interrupt is lsc
     836             :  *
     837             :  * Determime if external Base T PHY interrupt cause is high temperature
     838             :  * failure alarm or link status change.
     839             :  *
     840             :  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
     841             :  * failure alarm, else return PHY access status.
     842             :  */
     843           0 : int32_t ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
     844             : {
     845             :         uint32_t status;
     846           0 :         uint16_t reg;
     847             : 
     848           0 :         *lsc = FALSE;
     849             : 
     850             :         /* Vendor alarm triggered */
     851           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
     852             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     853             :                                       &reg);
     854             : 
     855           0 :         if (status != IXGBE_SUCCESS ||
     856           0 :             !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
     857           0 :                 return status;
     858             : 
     859             :         /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
     860           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
     861             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     862             :                                       &reg);
     863             : 
     864           0 :         if (status != IXGBE_SUCCESS ||
     865           0 :             !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
     866             :             IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
     867           0 :                 return status;
     868             : 
     869             :         /* Global alarm triggered */
     870           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
     871             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     872             :                                       &reg);
     873             : 
     874           0 :         if (status != IXGBE_SUCCESS)
     875           0 :                 return status;
     876             : 
     877             :         /* If high temperature failure, then return over temp error and exit */
     878           0 :         if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
     879             :                 /* power down the PHY in case the PHY FW didn't already */
     880           0 :                 ixgbe_set_copper_phy_power(hw, FALSE);
     881           0 :                 return IXGBE_ERR_OVERTEMP;
     882           0 :         } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
     883             :                 /*  device fault alarm triggered */
     884           0 :                 status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
     885             :                                           IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     886             :                                           &reg);
     887             : 
     888           0 :                 if (status != IXGBE_SUCCESS)
     889           0 :                         return status;
     890             : 
     891             :                 /* if device fault was due to high temp alarm handle and exit */
     892           0 :                 if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
     893             :                         /* power down the PHY in case the PHY FW didn't */
     894           0 :                         ixgbe_set_copper_phy_power(hw, FALSE);
     895           0 :                         return IXGBE_ERR_OVERTEMP;
     896             :                 }
     897             :         }
     898             : 
     899             :         /* Vendor alarm 2 triggered */
     900           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
     901             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
     902             : 
     903           0 :         if (status != IXGBE_SUCCESS ||
     904           0 :             !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
     905           0 :                 return status;
     906             : 
     907             :         /* link connect/disconnect event occurred */
     908           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
     909             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
     910             : 
     911           0 :         if (status != IXGBE_SUCCESS)
     912           0 :                 return status;
     913             : 
     914             :         /* Indicate LSC */
     915           0 :         if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
     916           0 :                 *lsc = TRUE;
     917             : 
     918           0 :         return IXGBE_SUCCESS;
     919           0 : }
     920             : 
     921             : /**
     922             :  * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
     923             :  * @hw: pointer to hardware structure
     924             :  *
     925             :  * Enable link status change and temperature failure alarm for the external
     926             :  * Base T PHY
     927             :  *
     928             :  * Returns PHY access status
     929             :  */
     930           0 : int32_t ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
     931             : {
     932             :         uint32_t status;
     933           0 :         uint16_t reg;
     934           0 :         bool lsc;
     935             : 
     936             :         /* Clear interrupt flags */
     937           0 :         status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
     938             : 
     939             :         /* Enable link status change alarm */
     940           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
     941             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
     942             : 
     943           0 :         if (status != IXGBE_SUCCESS)
     944           0 :                 return status;
     945             : 
     946           0 :         reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
     947             : 
     948           0 :         status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
     949             :                                        IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
     950             : 
     951           0 :         if (status != IXGBE_SUCCESS)
     952           0 :                 return status;
     953             : 
     954             :         /* Enables high temperature failure alarm */
     955           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
     956             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     957             :                                       &reg);
     958             : 
     959           0 :         if (status != IXGBE_SUCCESS)
     960           0 :                 return status;
     961             : 
     962           0 :         reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN;
     963             : 
     964           0 :         status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
     965             :                                        IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     966             :                                        reg);
     967             : 
     968           0 :         if (status != IXGBE_SUCCESS)
     969           0 :                 return status;
     970             : 
     971             :         /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
     972           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
     973             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     974             :                                       &reg);
     975             : 
     976           0 :         if (status != IXGBE_SUCCESS)
     977           0 :                 return status;
     978             : 
     979           0 :         reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
     980             :                 IXGBE_MDIO_GLOBAL_ALARM_1_INT);
     981             : 
     982           0 :         status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
     983             :                                        IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     984             :                                        reg);
     985             : 
     986           0 :         if (status != IXGBE_SUCCESS)
     987           0 :                 return status;
     988             : 
     989             :         /* Enable chip-wide vendor alarm */
     990           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
     991             :                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
     992             :                                       &reg);
     993             : 
     994           0 :         if (status != IXGBE_SUCCESS)
     995           0 :                 return status;
     996             : 
     997           0 :         reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
     998             : 
     999           0 :         status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
    1000             :                                        IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
    1001             :                                        reg);
    1002             : 
    1003           0 :         return status;
    1004           0 : }
    1005             : 
    1006             : /**
    1007             :  *  ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
    1008             :  *  @hw: pointer to hardware structure
    1009             :  *  @speed: link speed
    1010             :  *
    1011             :  *  Configures the integrated KR PHY.
    1012             :  **/
    1013           0 : int32_t ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
    1014             :                                     ixgbe_link_speed speed)
    1015             : {
    1016             :         int32_t status;
    1017           0 :         uint32_t reg_val;
    1018             : 
    1019           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1020           0 :                 IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1021             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1022           0 :         if (status)
    1023           0 :                 return status;
    1024             : 
    1025           0 :         reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
    1026           0 :         reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
    1027             :                      IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
    1028             : 
    1029             :         /* Advertise 10G support. */
    1030           0 :         if (speed & IXGBE_LINK_SPEED_10GB_FULL)
    1031           0 :                 reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
    1032             : 
    1033             :         /* Advertise 1G support. */
    1034           0 :         if (speed & IXGBE_LINK_SPEED_1GB_FULL)
    1035           0 :                 reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
    1036             : 
    1037             :         /* Restart auto-negotiation. */
    1038           0 :         reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
    1039           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1040           0 :                 IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1041             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1042             : 
    1043           0 :         return status;
    1044           0 : }
    1045             : 
    1046             : /**
    1047             :  *  ixgbe_init_phy_ops_X550em - PHY/SFP specific init
    1048             :  *  @hw: pointer to hardware structure
    1049             :  *
    1050             :  *  Initialize any function pointers that were not able to be
    1051             :  *  set during init_shared_code because the PHY/SFP type was
    1052             :  *  not known.  Perform the SFP init if necessary.
    1053             :  */
    1054           0 : int32_t ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
    1055             : {
    1056           0 :         struct ixgbe_phy_info *phy = &hw->phy;
    1057             :         ixgbe_link_speed speed;
    1058             :         int32_t ret_val;
    1059             : 
    1060             :         DEBUGFUNC("ixgbe_init_phy_ops_X550em");
    1061             : 
    1062           0 :         hw->mac.ops.set_lan_id(hw);
    1063             : 
    1064           0 :         if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
    1065           0 :                 phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
    1066           0 :                 ixgbe_setup_mux_ctl(hw);
    1067             : 
    1068             :                 /* Save NW management interface connected on board. This is used
    1069             :                  * to determine internal PHY mode.
    1070             :                  */
    1071           0 :                 phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
    1072           0 :                 if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
    1073             :                         speed = IXGBE_LINK_SPEED_10GB_FULL |
    1074             :                                 IXGBE_LINK_SPEED_1GB_FULL;
    1075           0 :                 }
    1076           0 :                 phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
    1077           0 :         }
    1078             : 
    1079             :         /* Identify the PHY or SFP module */
    1080           0 :         ret_val = phy->ops.identify(hw);
    1081           0 :         if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
    1082           0 :                 return ret_val;
    1083             : 
    1084             :         /* Setup function pointers based on detected hardware */
    1085           0 :         ixgbe_init_mac_link_ops_X550em(hw);
    1086           0 :         if (phy->sfp_type != ixgbe_sfp_type_unknown)
    1087           0 :                 phy->ops.reset = NULL;
    1088             : 
    1089             :         /* Set functions pointers based on phy type */
    1090           0 :         switch (hw->phy.type) {
    1091             :         case ixgbe_phy_x550em_kx4:
    1092           0 :                 phy->ops.setup_link = NULL;
    1093           0 :                 phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
    1094           0 :                 phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
    1095           0 :                 break;
    1096             :         case ixgbe_phy_x550em_kr:
    1097           0 :                 phy->ops.setup_link = ixgbe_setup_kr_x550em;
    1098           0 :                 phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
    1099           0 :                 phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
    1100           0 :                 break;
    1101             :         case ixgbe_phy_x550em_ext_t:
    1102             :                 /* Save NW management interface connected on board. This is used
    1103             :                  * to determine internal PHY mode
    1104             :                  */
    1105           0 :                 phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
    1106             : 
    1107             :                 /* If internal link mode is XFI, then setup iXFI internal link,
    1108             :                  * else setup KR now.
    1109             :                  */
    1110           0 :                 if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
    1111           0 :                         phy->ops.setup_internal_link =
    1112             :                                               ixgbe_setup_internal_phy_t_x550em;
    1113           0 :                 } else {
    1114             :                         speed = IXGBE_LINK_SPEED_10GB_FULL |
    1115             :                                 IXGBE_LINK_SPEED_1GB_FULL;
    1116           0 :                         ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
    1117             :                 }
    1118             : 
    1119           0 :                 phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
    1120           0 :                 phy->ops.reset = ixgbe_reset_phy_t_X550em;
    1121           0 :                 break;
    1122             :         default:
    1123             :                 break;
    1124             :         }
    1125           0 :         return ret_val;
    1126           0 : }
    1127             : 
    1128             : /**
    1129             :  *  ixgbe_reset_hw_X550em - Perform hardware reset
    1130             :  *  @hw: pointer to hardware structure
    1131             :  *
    1132             :  *  Resets the hardware by resetting the transmit and receive units, masks
    1133             :  *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
    1134             :  *  reset.
    1135             :  */
    1136           0 : int32_t ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
    1137             : {
    1138           0 :         ixgbe_link_speed link_speed;
    1139             :         int32_t status;
    1140             :         uint32_t ctrl = 0;
    1141             :         uint32_t i;
    1142             :         uint32_t hlreg0;
    1143           0 :         bool link_up = FALSE;
    1144             : 
    1145             :         DEBUGFUNC("ixgbe_reset_hw_X550em");
    1146             : 
    1147             :         /* Call adapter stop to disable Tx/Rx and clear interrupts */
    1148           0 :         status = hw->mac.ops.stop_adapter(hw);
    1149           0 :         if (status != IXGBE_SUCCESS)
    1150           0 :                 return status;
    1151             : 
    1152             :         /* flush pending Tx transactions */
    1153           0 :         ixgbe_clear_tx_pending(hw);
    1154             : 
    1155           0 :         if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
    1156             :                 /* Config MDIO clock speed before the first MDIO PHY access */
    1157           0 :                 hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
    1158           0 :                 hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
    1159           0 :                 IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
    1160           0 :         }
    1161             : 
    1162             :         /* PHY ops must be identified and initialized prior to reset */
    1163           0 :         status = hw->phy.ops.init(hw);
    1164             : 
    1165           0 :         if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
    1166           0 :                 return status;
    1167             : 
    1168             :         /* start the external PHY */
    1169           0 :         if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
    1170           0 :                 status = ixgbe_init_ext_t_x550em(hw);
    1171           0 :                 if (status)
    1172           0 :                         return status;
    1173             :         }
    1174             : 
    1175             :         /* Setup SFP module if there is one present. */
    1176           0 :         if (hw->phy.sfp_setup_needed) {
    1177           0 :                 status = hw->mac.ops.setup_sfp(hw);
    1178           0 :                 hw->phy.sfp_setup_needed = FALSE;
    1179           0 :         }
    1180             : 
    1181           0 :         if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
    1182           0 :                 return status;
    1183             : 
    1184             :         /* Reset PHY */
    1185           0 :         if (!hw->phy.reset_disable && hw->phy.ops.reset)
    1186           0 :                 hw->phy.ops.reset(hw);
    1187             : 
    1188             : mac_reset_top:
    1189             :         /* Issue global reset to the MAC.  Needs to be SW reset if link is up.
    1190             :          * If link reset is used when link is up, it might reset the PHY when
    1191             :          * mng is using it.  If link is down or the flag to force full link
    1192             :          * reset is set, then perform link reset.
    1193             :          */
    1194             :         ctrl = IXGBE_CTRL_LNK_RST;
    1195           0 :         if (!hw->force_full_reset) {
    1196           0 :                 hw->mac.ops.check_link(hw, &link_speed, &link_up, FALSE);
    1197           0 :                 if (link_up)
    1198           0 :                         ctrl = IXGBE_CTRL_RST;
    1199             :         }
    1200             : 
    1201           0 :         ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
    1202           0 :         IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
    1203           0 :         IXGBE_WRITE_FLUSH(hw);
    1204             : 
    1205             :         /* Poll for reset bit to self-clear meaning reset is complete */
    1206           0 :         for (i = 0; i < 10; i++) {
    1207           0 :                 usec_delay(1);
    1208           0 :                 ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
    1209           0 :                 if (!(ctrl & IXGBE_CTRL_RST_MASK))
    1210             :                         break;
    1211             :         }
    1212             : 
    1213           0 :         if (ctrl & IXGBE_CTRL_RST_MASK) {
    1214             :                 status = IXGBE_ERR_RESET_FAILED;
    1215             :                 DEBUGOUT("Reset polling failed to complete.\n");
    1216           0 :         }
    1217             : 
    1218           0 :         msec_delay(50);
    1219             : 
    1220             :         /* Double resets are required for recovery from certain error
    1221             :          * conditions.  Between resets, it is necessary to stall to
    1222             :          * allow time for any pending HW events to complete.
    1223             :          */
    1224           0 :         if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
    1225           0 :                 hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
    1226           0 :                 goto mac_reset_top;
    1227             :         }
    1228             : 
    1229             :         /* Store the permanent mac address */
    1230           0 :         hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
    1231             : 
    1232             :         /* Store MAC address from RAR0, clear receive address registers, and
    1233             :          * clear the multicast table.  Also reset num_rar_entries to 128,
    1234             :          * since we modify this value when programming the SAN MAC address.
    1235             :          */
    1236           0 :         hw->mac.num_rar_entries = 128;
    1237           0 :         hw->mac.ops.init_rx_addrs(hw);
    1238             : 
    1239           0 :         if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
    1240           0 :                 ixgbe_setup_mux_ctl(hw);
    1241             : 
    1242           0 :         return status;
    1243           0 : }
    1244             : 
    1245             : /**
    1246             :  * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
    1247             :  * @hw: pointer to hardware structure
    1248             :  */
    1249           0 : int32_t ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
    1250             : {
    1251             :         uint32_t status;
    1252           0 :         uint16_t reg;
    1253             : 
    1254           0 :         status = hw->phy.ops.read_reg(hw,
    1255             :                                       IXGBE_MDIO_TX_VENDOR_ALARMS_3,
    1256             :                                       IXGBE_MDIO_PMA_PMD_DEV_TYPE,
    1257             :                                       &reg);
    1258             : 
    1259           0 :         if (status != IXGBE_SUCCESS)
    1260           0 :                 return status;
    1261             : 
    1262             :         /* If PHY FW reset completed bit is set then this is the first
    1263             :          * SW instance after a power on so the PHY FW must be un-stalled.
    1264             :          */
    1265           0 :         if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
    1266           0 :                 status = hw->phy.ops.read_reg(hw,
    1267             :                                         IXGBE_MDIO_GLOBAL_RES_PR_10,
    1268             :                                         IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
    1269             :                                         &reg);
    1270             : 
    1271           0 :                 if (status != IXGBE_SUCCESS)
    1272           0 :                         return status;
    1273             : 
    1274           0 :                 reg &= ~IXGBE_MDIO_POWER_UP_STALL;
    1275             : 
    1276           0 :                 status = hw->phy.ops.write_reg(hw,
    1277             :                                         IXGBE_MDIO_GLOBAL_RES_PR_10,
    1278             :                                         IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
    1279             :                                         reg);
    1280             : 
    1281           0 :                 if (status != IXGBE_SUCCESS)
    1282           0 :                         return status;
    1283             :         }
    1284             : 
    1285           0 :         return status;
    1286           0 : }
    1287             : 
    1288             : /**
    1289             :  *  ixgbe_setup_kr_x550em - Configure the KR PHY.
    1290             :  *  @hw: pointer to hardware structure
    1291             :  *
    1292             :  *  Configures the integrated KR PHY.
    1293             :  **/
    1294           0 : int32_t ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
    1295             : {
    1296           0 :         return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
    1297             : }
    1298             : 
    1299             : /**
    1300             :  *  ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
    1301             :  *  @hw: pointer to hardware structure
    1302             :  *
    1303             :  *  Configure the external PHY and the integrated KR PHY for SFP support.
    1304             :  **/
    1305           0 : int32_t ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
    1306             :                                         ixgbe_link_speed speed,
    1307             :                                         bool autoneg_wait_to_complete)
    1308             : {
    1309             :         int32_t ret_val;
    1310             :         uint16_t reg_slice, reg_val;
    1311           0 :         bool setup_linear = FALSE;
    1312             : 
    1313             :         /* Check if SFP module is supported and linear */
    1314           0 :         ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
    1315             : 
    1316             :         /* If no SFP module present, then return success. Return success since
    1317             :          * there is no reason to configure CS4227 and SFP not present error is
    1318             :          * not excepted in the setup MAC link flow.
    1319             :          */
    1320           0 :         if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
    1321           0 :                 return IXGBE_SUCCESS;
    1322             : 
    1323           0 :         if (ret_val != IXGBE_SUCCESS)
    1324           0 :                 return ret_val;
    1325             : 
    1326           0 :         if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
    1327             :                 /* Configure CS4227 LINE side to 10G SR. */
    1328           0 :                 reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB +
    1329           0 :                             (hw->bus.lan_id << 12);
    1330             :                 reg_val = IXGBE_CS4227_SPEED_10G;
    1331           0 :                 ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
    1332             :                                                          reg_slice, reg_val);
    1333             : 
    1334           0 :                 reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
    1335           0 :                             (hw->bus.lan_id << 12);
    1336             :                 reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
    1337           0 :                 ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
    1338             :                                                          reg_slice, reg_val);
    1339             : 
    1340             :                 /* Configure CS4227 for HOST connection rate then type. */
    1341           0 :                 reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB +
    1342           0 :                             (hw->bus.lan_id << 12);
    1343           0 :                 reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ?
    1344             :                 IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
    1345           0 :                 ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
    1346             :                                                          reg_slice, reg_val);
    1347             : 
    1348           0 :                 reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB +
    1349           0 :                             (hw->bus.lan_id << 12);
    1350           0 :                 if (setup_linear)
    1351           0 :                         reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
    1352             :                 else
    1353             :                         reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
    1354           0 :                 ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
    1355             :                                                          reg_slice, reg_val);
    1356             : 
    1357             :                 /* Setup XFI internal link. */
    1358           0 :                 ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
    1359           0 :         } else {
    1360             :                 /* Configure internal PHY for KR/KX. */
    1361           0 :                 ixgbe_setup_kr_speed_x550em(hw, speed);
    1362             : 
    1363             :                 /* Configure CS4227 LINE side to proper mode. */
    1364           0 :                 reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
    1365           0 :                             (hw->bus.lan_id << 12);
    1366           0 :                 if (setup_linear)
    1367           0 :                         reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
    1368             :                 else
    1369             :                         reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
    1370           0 :                 ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
    1371             :                                                          reg_slice, reg_val);
    1372             :         }
    1373           0 :         return ret_val;
    1374           0 : }
    1375             : 
    1376             : /**
    1377             :  *  ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
    1378             :  *  @hw: pointer to hardware structure
    1379             :  *  @speed: the link speed to force
    1380             :  *
    1381             :  *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
    1382             :  *  internal and external PHY at a specific speed, without autonegotiation.
    1383             :  **/
    1384           0 : int32_t ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
    1385             : {
    1386             :         int32_t status;
    1387           0 :         uint32_t reg_val;
    1388             : 
    1389             :         /* Disable AN and force speed to 10G Serial. */
    1390           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1391           0 :                                         IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1392             :                                         IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1393           0 :         if (status != IXGBE_SUCCESS)
    1394           0 :                 return status;
    1395             : 
    1396           0 :         reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
    1397           0 :         reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
    1398             : 
    1399             :         /* Select forced link speed for internal PHY. */
    1400           0 :         switch (*speed) {
    1401             :         case IXGBE_LINK_SPEED_10GB_FULL:
    1402           0 :                 reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
    1403           0 :                 break;
    1404             :         case IXGBE_LINK_SPEED_1GB_FULL:
    1405           0 :                 reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
    1406           0 :                 break;
    1407             :         default:
    1408             :                 /* Other link speeds are not supported by internal KR PHY. */
    1409           0 :                 return IXGBE_ERR_LINK_SETUP;
    1410             :         }
    1411             : 
    1412           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1413           0 :                                         IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1414           0 :                                         IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1415           0 :         if (status != IXGBE_SUCCESS)
    1416           0 :                 return status;
    1417             : 
    1418             :         /* Disable training protocol FSM. */
    1419           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1420           0 :                                 IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
    1421             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1422           0 :         if (status != IXGBE_SUCCESS)
    1423           0 :                 return status;
    1424           0 :         reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
    1425           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1426           0 :                                 IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
    1427             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1428           0 :         if (status != IXGBE_SUCCESS)
    1429           0 :                 return status;
    1430             : 
    1431             :         /* Disable Flex from training TXFFE. */
    1432           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1433           0 :                                 IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
    1434             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1435           0 :         if (status != IXGBE_SUCCESS)
    1436           0 :                 return status;
    1437           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
    1438           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
    1439           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
    1440           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1441           0 :                                 IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
    1442             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1443           0 :         if (status != IXGBE_SUCCESS)
    1444           0 :                 return status;
    1445           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1446           0 :                                 IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
    1447             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1448           0 :         if (status != IXGBE_SUCCESS)
    1449           0 :                 return status;
    1450           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN;
    1451           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
    1452           0 :         reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
    1453           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1454           0 :                                 IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
    1455             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1456           0 :         if (status != IXGBE_SUCCESS)
    1457           0 :                 return status;
    1458             : 
    1459             :         /* Enable override for coefficients. */
    1460           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1461           0 :                                 IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
    1462             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1463           0 :         if (status != IXGBE_SUCCESS)
    1464           0 :                 return status;
    1465           0 :         reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN;
    1466           0 :         reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN;
    1467           0 :         reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
    1468           0 :         reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
    1469           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1470           0 :                                 IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
    1471             :                                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1472           0 :         if (status != IXGBE_SUCCESS)
    1473           0 :                 return status;
    1474             : 
    1475             :         /* Toggle port SW reset by AN reset. */
    1476           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1477           0 :                                         IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1478             :                                         IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1479           0 :         if (status != IXGBE_SUCCESS)
    1480           0 :                 return status;
    1481           0 :         reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
    1482           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1483           0 :                                         IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1484             :                                         IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1485             : 
    1486           0 :         return status;
    1487           0 : }
    1488             : 
    1489             : /**
    1490             :  * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
    1491             :  * @hw: address of hardware structure
    1492             :  * @link_up: address of boolean to indicate link status
    1493             :  *
    1494             :  * Returns error code if unable to get link status.
    1495             :  */
    1496           0 : int32_t ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
    1497             : {
    1498             :         uint32_t ret;
    1499           0 :         uint16_t autoneg_status;
    1500             : 
    1501           0 :         *link_up = FALSE;
    1502             : 
    1503             :         /* read this twice back to back to indicate current status */
    1504           0 :         ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
    1505             :                                    IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    1506             :                                    &autoneg_status);
    1507           0 :         if (ret != IXGBE_SUCCESS)
    1508           0 :                 return ret;
    1509             : 
    1510           0 :         ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
    1511             :                                    IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    1512             :                                    &autoneg_status);
    1513           0 :         if (ret != IXGBE_SUCCESS)
    1514           0 :                 return ret;
    1515             : 
    1516           0 :         *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
    1517             : 
    1518           0 :         return IXGBE_SUCCESS;
    1519           0 : }
    1520             : 
    1521             : /**
    1522             :  * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
    1523             :  * @hw: point to hardware structure
    1524             :  *
    1525             :  * Configures the link between the integrated KR PHY and the external X557 PHY
    1526             :  * The driver will call this function when it gets a link status change
    1527             :  * interrupt from the X557 PHY. This function configures the link speed
    1528             :  * between the PHYs to match the link speed of the BASE-T link.
    1529             :  *
    1530             :  * A return of a non-zero value indicates an error, and the base driver should
    1531             :  * not report link up.
    1532             :  */
    1533           0 : int32_t ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
    1534             : {
    1535           0 :         ixgbe_link_speed force_speed;
    1536           0 :         bool link_up;
    1537             :         uint32_t status;
    1538           0 :         uint16_t speed;
    1539             : 
    1540           0 :         if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
    1541           0 :                 return IXGBE_ERR_CONFIG;
    1542             : 
    1543             :         /* If link is not up, then there is no setup necessary so return  */
    1544           0 :         status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
    1545           0 :         if (status != IXGBE_SUCCESS)
    1546           0 :                 return status;
    1547             : 
    1548           0 :         if (!link_up)
    1549           0 :                 return IXGBE_SUCCESS;
    1550             : 
    1551           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
    1552             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    1553             :                                       &speed);
    1554           0 :         if (status != IXGBE_SUCCESS)
    1555           0 :                 return status;
    1556             : 
    1557             :         /* If link is not still up, then no setup is necessary so return */
    1558           0 :         status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
    1559           0 :         if (status != IXGBE_SUCCESS)
    1560           0 :                 return status;
    1561           0 :         if (!link_up)
    1562           0 :                 return IXGBE_SUCCESS;
    1563             : 
    1564             :         /* clear everything but the speed and duplex bits */
    1565           0 :         speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
    1566             : 
    1567           0 :         switch (speed) {
    1568             :         case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
    1569           0 :                 force_speed = IXGBE_LINK_SPEED_10GB_FULL;
    1570           0 :                 break;
    1571             :         case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
    1572           0 :                 force_speed = IXGBE_LINK_SPEED_1GB_FULL;
    1573           0 :                 break;
    1574             :         default:
    1575             :                 /* Internal PHY does not support anything else */
    1576           0 :                 return IXGBE_ERR_INVALID_LINK_SETTINGS;
    1577             :         }
    1578             : 
    1579           0 :         return ixgbe_setup_ixfi_x550em(hw, &force_speed);
    1580           0 : }
    1581             : 
    1582             : /**
    1583             :  *  ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback.
    1584             :  *  @hw: pointer to hardware structure
    1585             :  *
    1586             :  *  Configures the integrated KR PHY to use internal loopback mode.
    1587             :  **/
    1588           0 : int32_t ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
    1589             : {
    1590             :         int32_t status;
    1591           0 :         uint32_t reg_val;
    1592             : 
    1593             :         /* Disable AN and force speed to 10G Serial. */
    1594           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1595           0 :                 IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1596             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1597           0 :         if (status != IXGBE_SUCCESS)
    1598           0 :                 return status;
    1599           0 :         reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
    1600           0 :         reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
    1601           0 :         reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
    1602           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1603           0 :                 IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
    1604             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1605           0 :         if (status != IXGBE_SUCCESS)
    1606           0 :                 return status;
    1607             : 
    1608             :         /* Set near-end loopback clocks. */
    1609           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1610           0 :                 IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
    1611             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1612           0 :         if (status != IXGBE_SUCCESS)
    1613           0 :                 return status;
    1614           0 :         reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
    1615           0 :         reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
    1616           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1617           0 :                 IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
    1618             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1619           0 :         if (status != IXGBE_SUCCESS)
    1620           0 :                 return status;
    1621             : 
    1622             :         /* Set loopback enable. */
    1623           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1624           0 :                 IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
    1625             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1626           0 :         if (status != IXGBE_SUCCESS)
    1627           0 :                 return status;
    1628           0 :         reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
    1629           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1630           0 :                 IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
    1631             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1632           0 :         if (status != IXGBE_SUCCESS)
    1633           0 :                 return status;
    1634             : 
    1635             :         /* Training bypass. */
    1636           0 :         status = ixgbe_read_iosf_sb_reg_x550(hw,
    1637           0 :                 IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
    1638             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    1639           0 :         if (status != IXGBE_SUCCESS)
    1640           0 :                 return status;
    1641           0 :         reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
    1642           0 :         status = ixgbe_write_iosf_sb_reg_x550(hw,
    1643           0 :                 IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
    1644             :                 IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    1645             : 
    1646           0 :         return status;
    1647           0 : }
    1648             : 
    1649             : /**
    1650             :  *  ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
    1651             :  *  assuming that the semaphore is already obtained.
    1652             :  *  @hw: pointer to hardware structure
    1653             :  *  @offset: offset of  word in the EEPROM to read
    1654             :  *  @data: word read from the EEPROM
    1655             :  *
    1656             :  *  Reads a 16 bit word from the EEPROM using the hostif.
    1657             :  **/
    1658           0 : int32_t ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset,
    1659             :                                        uint16_t *data)
    1660             : {
    1661             :         int32_t status;
    1662           0 :         struct ixgbe_hic_read_shadow_ram buffer;
    1663             : 
    1664             :         DEBUGFUNC("ixgbe_read_ee_hostif_data_X550");
    1665           0 :         buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
    1666           0 :         buffer.hdr.req.buf_lenh = 0;
    1667           0 :         buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
    1668           0 :         buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
    1669             : 
    1670             :         /* convert offset from words to bytes */
    1671           0 :         buffer.address = htobe32(offset * 2);
    1672             :         /* one word */
    1673           0 :         buffer.length = htobe16(sizeof(uint16_t));
    1674             : 
    1675           0 :         status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer,
    1676             :                                               sizeof(buffer),
    1677             :                                               IXGBE_HI_COMMAND_TIMEOUT, FALSE);
    1678             : 
    1679           0 :         if (status)
    1680           0 :                 return status;
    1681             : 
    1682           0 :         *data = (uint16_t)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
    1683             :                                           FW_NVM_DATA_OFFSET);
    1684             : 
    1685           0 :         return 0;
    1686           0 : }
    1687             : 
    1688             : /**
    1689             :  *  ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command
    1690             :  *  @hw: pointer to hardware structure
    1691             :  *  @offset: offset of  word in the EEPROM to read
    1692             :  *  @data: word read from the EEPROM
    1693             :  *
    1694             :  *  Reads a 16 bit word from the EEPROM using the hostif.
    1695             :  **/
    1696           0 : int32_t ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset,
    1697             :                                   uint16_t *data)
    1698             : {
    1699             :         int32_t status = IXGBE_SUCCESS;
    1700             : 
    1701             :         DEBUGFUNC("ixgbe_read_ee_hostif_X550");
    1702             : 
    1703           0 :         if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
    1704             :             IXGBE_SUCCESS) {
    1705           0 :                 status = ixgbe_read_ee_hostif_data_X550(hw, offset, data);
    1706           0 :                 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
    1707           0 :         } else {
    1708             :                 status = IXGBE_ERR_SWFW_SYNC;
    1709             :         }
    1710             : 
    1711           0 :         return status;
    1712             : }
    1713             : 
    1714             : /**
    1715             :  *  ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif
    1716             :  *  @hw: pointer to hardware structure
    1717             :  *  @offset: offset of  word in the EEPROM to read
    1718             :  *  @words: number of words
    1719             :  *  @data: word(s) read from the EEPROM
    1720             :  *
    1721             :  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
    1722             :  **/
    1723           0 : int32_t ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
    1724             :                                          uint16_t offset, uint16_t words,
    1725             :                                          uint16_t *data)
    1726             : {
    1727           0 :         struct ixgbe_hic_read_shadow_ram buffer;
    1728             :         uint32_t current_word = 0;
    1729             :         uint16_t words_to_read;
    1730             :         int32_t status;
    1731             :         uint32_t i;
    1732             : 
    1733             :         DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550");
    1734             : 
    1735             :         /* Take semaphore for the entire operation. */
    1736           0 :         status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
    1737           0 :         if (status) {
    1738             :                 DEBUGOUT("EEPROM read buffer - semaphore failed\n");
    1739           0 :                 return status;
    1740             :         }
    1741           0 :         while (words) {
    1742           0 :                 if (words > FW_MAX_READ_BUFFER_SIZE / 2)
    1743           0 :                         words_to_read = FW_MAX_READ_BUFFER_SIZE / 2;
    1744             :                 else
    1745             :                         words_to_read = words;
    1746             : 
    1747           0 :                 buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
    1748           0 :                 buffer.hdr.req.buf_lenh = 0;
    1749           0 :                 buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
    1750           0 :                 buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
    1751             : 
    1752             :                 /* convert offset from words to bytes */
    1753           0 :                 buffer.address = htobe32((offset + current_word) * 2);
    1754           0 :                 buffer.length = htobe16(words_to_read * 2);
    1755             : 
    1756           0 :                 status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer,
    1757             :                                                       sizeof(buffer),
    1758             :                                                       IXGBE_HI_COMMAND_TIMEOUT,
    1759             :                                                       FALSE);
    1760             : 
    1761           0 :                 if (status) {
    1762             :                         DEBUGOUT("Host interface command failed\n");
    1763             :                         goto out;
    1764             :                 }
    1765             : 
    1766           0 :                 for (i = 0; i < words_to_read; i++) {
    1767           0 :                         uint32_t reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) +
    1768           0 :                                   2 * i;
    1769           0 :                         uint32_t value = IXGBE_READ_REG(hw, reg);
    1770             : 
    1771           0 :                         data[current_word] = (uint16_t)(value & 0xffff);
    1772           0 :                         current_word++;
    1773           0 :                         i++;
    1774           0 :                         if (i < words_to_read) {
    1775           0 :                                 value >>= 16;
    1776           0 :                                 data[current_word] = (uint16_t)(value & 0xffff);
    1777           0 :                                 current_word++;
    1778           0 :                         }
    1779             :                 }
    1780           0 :                 words -= words_to_read;
    1781             :         }
    1782             : 
    1783             : out:
    1784           0 :         hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
    1785           0 :         return status;
    1786           0 : }
    1787             : 
    1788             : /**
    1789             :  *  ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
    1790             :  *  @hw: pointer to hardware structure
    1791             :  *  @offset: offset of  word in the EEPROM to write
    1792             :  *  @data: word write to the EEPROM
    1793             :  *
    1794             :  *  Write a 16 bit word to the EEPROM using the hostif.
    1795             :  **/
    1796           0 : int32_t ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, uint16_t offset,
    1797             :                                         uint16_t data)
    1798             : {
    1799             :         int32_t status;
    1800           0 :         struct ixgbe_hic_write_shadow_ram buffer;
    1801             : 
    1802             :         DEBUGFUNC("ixgbe_write_ee_hostif_data_X550");
    1803             : 
    1804           0 :         buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
    1805           0 :         buffer.hdr.req.buf_lenh = 0;
    1806           0 :         buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
    1807           0 :         buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
    1808             : 
    1809             :          /* one word */
    1810           0 :         buffer.length = htobe16(sizeof(uint16_t));
    1811           0 :         buffer.data = data;
    1812           0 :         buffer.address = htobe32(offset * 2);
    1813             : 
    1814           0 :         status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer,
    1815             :                                               sizeof(buffer),
    1816             :                                               IXGBE_HI_COMMAND_TIMEOUT, FALSE);
    1817             : 
    1818           0 :         return status;
    1819           0 : }
    1820             : 
    1821             : /**
    1822             :  *  ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif
    1823             :  *  @hw: pointer to hardware structure
    1824             :  *  @offset: offset of  word in the EEPROM to write
    1825             :  *  @data: word write to the EEPROM
    1826             :  *
    1827             :  *  Write a 16 bit word to the EEPROM using the hostif.
    1828             :  **/
    1829           0 : int32_t ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, uint16_t offset,
    1830             :                                    uint16_t data)
    1831             : {
    1832             :         int32_t status = IXGBE_SUCCESS;
    1833             : 
    1834             :         DEBUGFUNC("ixgbe_write_ee_hostif_X550");
    1835             : 
    1836           0 :         if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
    1837             :             IXGBE_SUCCESS) {
    1838           0 :                 status = ixgbe_write_ee_hostif_data_X550(hw, offset, data);
    1839           0 :                 hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
    1840           0 :         } else {
    1841             :                 DEBUGOUT("write ee hostif failed to get semaphore\n");
    1842             :                 status = IXGBE_ERR_SWFW_SYNC;
    1843             :         }
    1844             : 
    1845           0 :         return status;
    1846             : }
    1847             : 
    1848             : /**
    1849             :  * ixgbe_checksum_ptr_x550 - Checksum one pointer region
    1850             :  * @hw: pointer to hardware structure
    1851             :  * @ptr: pointer offset in eeprom
    1852             :  * @size: size of section pointed by ptr, if 0 first word will be used as size
    1853             :  * @csum: address of checksum to update
    1854             :  *
    1855             :  * Returns error status for any failure
    1856             :  */
    1857           0 : int32_t ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, uint16_t ptr,
    1858             :                                 uint16_t size, uint16_t *csum, uint16_t *buffer,
    1859             :                                 uint32_t buffer_size)
    1860             : {
    1861           0 :         uint16_t buf[256];
    1862             :         int32_t status;
    1863             :         uint16_t length, bufsz, i, start;
    1864             :         uint16_t *local_buffer;
    1865             : 
    1866             :         bufsz = sizeof(buf) / sizeof(buf[0]);
    1867             : 
    1868             :         /* Read a chunk at the pointer location */
    1869           0 :         if (!buffer) {
    1870           0 :                 status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
    1871           0 :                 if (status) {
    1872             :                         DEBUGOUT("Failed to read EEPROM image\n");
    1873           0 :                         return status;
    1874             :                 }
    1875             :                 local_buffer = buf;
    1876           0 :         } else {
    1877           0 :                 if (buffer_size < ptr)
    1878           0 :                         return  IXGBE_ERR_PARAM;
    1879           0 :                 local_buffer = &buffer[ptr];
    1880             :         }
    1881             : 
    1882           0 :         if (size) {
    1883             :                 start = 0;
    1884             :                 length = size;
    1885           0 :         } else {
    1886             :                 start = 1;
    1887           0 :                 length = local_buffer[0];
    1888             : 
    1889             :                 /* Skip pointer section if length is invalid. */
    1890           0 :                 if (length == 0xFFFF || length == 0 ||
    1891           0 :                     (ptr + length) >= hw->eeprom.word_size)
    1892           0 :                         return IXGBE_SUCCESS;
    1893             :         }
    1894             : 
    1895           0 :         if (buffer && ((uint32_t)start + (uint32_t)length > buffer_size))
    1896           0 :                 return IXGBE_ERR_PARAM;
    1897             : 
    1898           0 :         for (i = start; length; i++, length--) {
    1899           0 :                 if (i == bufsz && !buffer) {
    1900           0 :                         ptr += bufsz;
    1901             :                         i = 0;
    1902           0 :                         if (length < bufsz)
    1903           0 :                                 bufsz = length;
    1904             : 
    1905             :                         /* Read a chunk at the pointer location */
    1906           0 :                         status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr,
    1907           0 :                                                                   bufsz, buf);
    1908           0 :                         if (status) {
    1909             :                                 DEBUGOUT("Failed to read EEPROM image\n");
    1910           0 :                                 return status;
    1911             :                         }
    1912             :                 }
    1913           0 :                 *csum += local_buffer[i];
    1914             :         }
    1915           0 :         return IXGBE_SUCCESS;
    1916           0 : }
    1917             : 
    1918             : /**
    1919             :  *  ixgbe_calc_checksum_X550 - Calculates and returns the checksum
    1920             :  *  @hw: pointer to hardware structure
    1921             :  *  @buffer: pointer to buffer containing calculated checksum
    1922             :  *  @buffer_size: size of buffer
    1923             :  *
    1924             :  *  Returns a negative error code on error, or the 16-bit checksum
    1925             :  **/
    1926           0 : int32_t ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, uint16_t *buffer,
    1927             :                                  uint32_t buffer_size)
    1928             : {
    1929           0 :         uint16_t eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
    1930             :         uint16_t *local_buffer;
    1931             :         int32_t status;
    1932           0 :         uint16_t checksum = 0;
    1933             :         uint16_t pointer, i, size;
    1934             : 
    1935             :         DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550");
    1936             : 
    1937           0 :         hw->eeprom.ops.init_params(hw);
    1938             : 
    1939           0 :         if (!buffer) {
    1940             :                 /* Read pointer area */
    1941           0 :                 status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
    1942             :                                                      IXGBE_EEPROM_LAST_WORD + 1,
    1943           0 :                                                      eeprom_ptrs);
    1944           0 :                 if (status) {
    1945             :                         DEBUGOUT("Failed to read EEPROM image\n");
    1946           0 :                         return status;
    1947             :                 }
    1948             :                 local_buffer = eeprom_ptrs;
    1949           0 :         } else {
    1950           0 :                 if (buffer_size < IXGBE_EEPROM_LAST_WORD)
    1951           0 :                         return IXGBE_ERR_PARAM;
    1952             :                 local_buffer = buffer;
    1953             :         }
    1954             : 
    1955             :         /*
    1956             :          * For X550 hardware include 0x0-0x41 in the checksum, skip the
    1957             :          * checksum word itself
    1958             :          */
    1959           0 :         for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
    1960           0 :                 if (i != IXGBE_EEPROM_CHECKSUM)
    1961           0 :                         checksum += local_buffer[i];
    1962             : 
    1963             :         /*
    1964             :          * Include all data from pointers 0x3, 0x6-0xE.  This excludes the
    1965             :          * FW, PHY module, and PCIe Expansion/Option ROM pointers.
    1966             :          */
    1967           0 :         for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) {
    1968           0 :                 if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
    1969             :                         continue;
    1970             : 
    1971           0 :                 pointer = local_buffer[i];
    1972             : 
    1973             :                 /* Skip pointer section if the pointer is invalid. */
    1974           0 :                 if (pointer == 0xFFFF || pointer == 0 ||
    1975           0 :                     pointer >= hw->eeprom.word_size)
    1976             :                         continue;
    1977             : 
    1978           0 :                 switch (i) {
    1979             :                 case IXGBE_PCIE_GENERAL_PTR:
    1980             :                         size = IXGBE_IXGBE_PCIE_GENERAL_SIZE;
    1981           0 :                         break;
    1982             :                 case IXGBE_PCIE_CONFIG0_PTR:
    1983             :                 case IXGBE_PCIE_CONFIG1_PTR:
    1984             :                         size = IXGBE_PCIE_CONFIG_SIZE;
    1985           0 :                         break;
    1986             :                 default:
    1987             :                         size = 0;
    1988           0 :                         break;
    1989             :                 }
    1990             : 
    1991           0 :                 status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
    1992             :                                                 buffer, buffer_size);
    1993           0 :                 if (status)
    1994           0 :                         return status;
    1995             :         }
    1996             : 
    1997           0 :         checksum = (uint16_t)IXGBE_EEPROM_SUM - checksum;
    1998             : 
    1999           0 :         return (int32_t)checksum;
    2000           0 : }
    2001             : 
    2002             : /**
    2003             :  *  ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
    2004             :  *  @hw: pointer to hardware structure
    2005             :  *
    2006             :  *  Returns a negative error code on error, or the 16-bit checksum
    2007             :  **/
    2008           0 : int32_t ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
    2009             : {
    2010           0 :         return ixgbe_calc_checksum_X550(hw, NULL, 0);
    2011             : }
    2012             : 
    2013             : /**
    2014             :  *  ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
    2015             :  *  @hw: pointer to hardware structure
    2016             :  *  @checksum_val: calculated checksum
    2017             :  *
    2018             :  *  Performs checksum calculation and validates the EEPROM checksum.  If the
    2019             :  *  caller does not need checksum_val, the value can be NULL.
    2020             :  **/
    2021           0 : int32_t ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, uint16_t *checksum_val)
    2022             : {
    2023             :         int32_t status;
    2024           0 :         uint16_t checksum;
    2025           0 :         uint16_t read_checksum = 0;
    2026             : 
    2027             :         DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550");
    2028             : 
    2029             :         /* Read the first word from the EEPROM. If this times out or fails, do
    2030             :          * not continue or we could be in for a very long wait while every
    2031             :          * EEPROM read fails
    2032             :          */
    2033           0 :         status = hw->eeprom.ops.read(hw, 0, &checksum);
    2034           0 :         if (status) {
    2035             :                 DEBUGOUT("EEPROM read failed\n");
    2036           0 :                 return status;
    2037             :         }
    2038             : 
    2039           0 :         status = hw->eeprom.ops.calc_checksum(hw);
    2040           0 :         if (status < 0)
    2041           0 :                 return status;
    2042             : 
    2043           0 :         checksum = (uint16_t)(status & 0xffff);
    2044             : 
    2045           0 :         status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
    2046             :                                            &read_checksum);
    2047           0 :         if (status)
    2048           0 :                 return status;
    2049             : 
    2050             :         /* Verify read checksum from EEPROM is the same as
    2051             :          * calculated checksum
    2052             :          */
    2053           0 :         if (read_checksum != checksum) {
    2054             :                 status = IXGBE_ERR_EEPROM_CHECKSUM;
    2055             :                 DEBUGOUT("Invalid EEPROM checksum\n");
    2056           0 :         }
    2057             : 
    2058             :         /* If the user cares, return the calculated checksum */
    2059           0 :         if (checksum_val)
    2060           0 :                 *checksum_val = checksum;
    2061             : 
    2062           0 :         return status;
    2063           0 : }
    2064             : 
    2065             : /**
    2066             :  * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash
    2067             :  * @hw: pointer to hardware structure
    2068             :  *
    2069             :  * After writing EEPROM to shadow RAM using EEWR register, software calculates
    2070             :  * checksum and updates the EEPROM and instructs the hardware to update
    2071             :  * the flash.
    2072             :  **/
    2073           0 : int32_t ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
    2074             : {
    2075             :         int32_t status;
    2076           0 :         uint16_t checksum = 0;
    2077             : 
    2078             :         DEBUGFUNC("ixgbe_update_eeprom_checksum_X550");
    2079             : 
    2080             :         /* Read the first word from the EEPROM. If this times out or fails, do
    2081             :          * not continue or we could be in for a very long wait while every
    2082             :          * EEPROM read fails
    2083             :          */
    2084           0 :         status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum);
    2085           0 :         if (status) {
    2086             :                 DEBUGOUT("EEPROM read failed\n");
    2087           0 :                 return status;
    2088             :         }
    2089             : 
    2090           0 :         status = ixgbe_calc_eeprom_checksum_X550(hw);
    2091           0 :         if (status < 0)
    2092           0 :                 return status;
    2093             : 
    2094           0 :         checksum = (uint16_t)(status & 0xffff);
    2095             : 
    2096           0 :         status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM,
    2097             :                                             checksum);
    2098           0 :         if (status)
    2099           0 :                 return status;
    2100             : 
    2101           0 :         status = ixgbe_update_flash_X550(hw);
    2102             : 
    2103           0 :         return status;
    2104           0 : }
    2105             : 
    2106             : /**
    2107             :  *  ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device
    2108             :  *  @hw: pointer to hardware structure
    2109             :  *
    2110             :  *  Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash.
    2111             :  **/
    2112           0 : int32_t ixgbe_update_flash_X550(struct ixgbe_hw *hw)
    2113             : {
    2114             :         int32_t status = IXGBE_SUCCESS;
    2115           0 :         union ixgbe_hic_hdr2 buffer;
    2116             : 
    2117             :         DEBUGFUNC("ixgbe_update_flash_X550");
    2118             : 
    2119           0 :         buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
    2120           0 :         buffer.req.buf_lenh = 0;
    2121           0 :         buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
    2122           0 :         buffer.req.checksum = FW_DEFAULT_CHECKSUM;
    2123             : 
    2124           0 :         status = ixgbe_host_interface_command(hw, (uint32_t *)&buffer,
    2125             :                                               sizeof(buffer),
    2126             :                                               IXGBE_HI_COMMAND_TIMEOUT, FALSE);
    2127             : 
    2128           0 :         return status;
    2129           0 : }
    2130             : 
    2131             : /**
    2132             :  *  ixgbe_get_supported_physical_layer_X550em - Returns physical layer type
    2133             :  *  @hw: pointer to hardware structure
    2134             :  *
    2135             :  *  Determines physical layer capabilities of the current configuration.
    2136             :  **/
    2137           0 : uint32_t ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
    2138             : {
    2139             :         uint32_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
    2140           0 :         uint16_t ext_ability = 0;
    2141             : 
    2142             :         DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
    2143             : 
    2144           0 :         hw->phy.ops.identify(hw);
    2145             : 
    2146           0 :         switch (hw->phy.type) {
    2147             :         case ixgbe_phy_x550em_kr:
    2148             :                 physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR |
    2149             :                                  IXGBE_PHYSICAL_LAYER_1000BASE_KX;
    2150           0 :                 break;
    2151             :         case ixgbe_phy_x550em_kx4:
    2152             :                 physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
    2153             :                                  IXGBE_PHYSICAL_LAYER_1000BASE_KX;
    2154           0 :                 break;
    2155             :         case ixgbe_phy_x550em_ext_t:
    2156           0 :                 hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
    2157             :                                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
    2158             :                                      &ext_ability);
    2159           0 :                 if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
    2160           0 :                         physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
    2161           0 :                 if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
    2162           0 :                         physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
    2163             :                 break;
    2164             :         default:
    2165             :                 break;
    2166             :         }
    2167             : 
    2168           0 :         if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
    2169           0 :                 physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw);
    2170             : 
    2171           0 :         return physical_layer;
    2172           0 : }
    2173             : 
    2174             : /**
    2175             :  * ixgbe_get_bus_info_x550em - Set PCI bus info
    2176             :  * @hw: pointer to hardware structure
    2177             :  *
    2178             :  * Sets bus link width and speed to unknown because X550em is
    2179             :  * not a PCI device.
    2180             :  **/
    2181           0 : int32_t ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
    2182             : {
    2183             : 
    2184             :         DEBUGFUNC("ixgbe_get_bus_info_x550em");
    2185             : 
    2186           0 :         hw->bus.width = ixgbe_bus_width_unknown;
    2187           0 :         hw->bus.speed = ixgbe_bus_speed_unknown;
    2188             : 
    2189           0 :         hw->mac.ops.set_lan_id(hw);
    2190             : 
    2191           0 :         return IXGBE_SUCCESS;
    2192             : }
    2193             : 
    2194             : /**
    2195             :  * ixgbe_disable_rx_x550 - Disable RX unit
    2196             :  *
    2197             :  * Enables the Rx DMA unit for x550
    2198             :  **/
    2199           0 : void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
    2200             : {
    2201             :         uint32_t rxctrl;
    2202             :         int32_t status;
    2203           0 :         struct ixgbe_hic_disable_rxen fw_cmd;
    2204             : 
    2205             :         DEBUGFUNC("ixgbe_disable_rx_dma_x550");
    2206             : 
    2207           0 :         rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
    2208           0 :         if (rxctrl & IXGBE_RXCTRL_RXEN) {
    2209           0 :                 fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
    2210           0 :                 fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
    2211           0 :                 fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
    2212           0 :                 fw_cmd.port_number = (uint8_t)hw->bus.lan_id;
    2213             : 
    2214           0 :                 status = ixgbe_host_interface_command(hw, (uint32_t *)&fw_cmd,
    2215             :                                         sizeof(struct ixgbe_hic_disable_rxen),
    2216             :                                         IXGBE_HI_COMMAND_TIMEOUT, TRUE);
    2217             : 
    2218             :                 /* If we fail - disable RX using register write */
    2219           0 :                 if (status) {
    2220           0 :                         rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
    2221           0 :                         if (rxctrl & IXGBE_RXCTRL_RXEN) {
    2222           0 :                                 rxctrl &= ~IXGBE_RXCTRL_RXEN;
    2223           0 :                                 IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
    2224           0 :                         }
    2225             :                 }
    2226             :         }
    2227           0 : }
    2228             : 
    2229             : /**
    2230             :  * ixgbe_get_lcd_x550em - Determine lowest common denominator
    2231             :  *  @hw: pointer to hardware structure
    2232             :  *  @lcd_speed: pointer to lowest common link speed
    2233             :  *
    2234             :  * Determine lowest common link speed with link partner.
    2235             :  **/
    2236           0 : int32_t ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed)
    2237             : {
    2238           0 :         uint16_t an_lp_status;
    2239             :         int32_t status;
    2240           0 :         uint16_t word = hw->eeprom.ctrl_word_3;
    2241             : 
    2242           0 :         *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
    2243             : 
    2244           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
    2245             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    2246             :                                       &an_lp_status);
    2247             : 
    2248           0 :         if (status != IXGBE_SUCCESS)
    2249           0 :                 return status;
    2250             : 
    2251             :         /* If link partner advertised 1G, return 1G */
    2252           0 :         if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) {
    2253           0 :                 *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL;
    2254           0 :                 return status;
    2255             :         }
    2256             : 
    2257             :         /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */
    2258           0 :         if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) ||
    2259           0 :             (word & NVM_INIT_CTRL_3_D10GMP_PORT0))
    2260           0 :                 return status;
    2261             : 
    2262             :         /* Link partner not capable of lower speeds, return 10G */
    2263           0 :         *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL;
    2264           0 :         return status;
    2265           0 : }
    2266             : 
    2267             : /**
    2268             :  *  ixgbe_setup_fc_X550em - Set up flow control
    2269             :  *  @hw: pointer to hardware structure
    2270             :  *
    2271             :  *  Called at init time to set up flow control.
    2272             :  **/
    2273           0 : int32_t ixgbe_setup_fc_X550em(struct ixgbe_hw *hw)
    2274             : {
    2275             :         int32_t ret_val = IXGBE_SUCCESS;
    2276           0 :         uint32_t pause, asm_dir, reg_val;
    2277             : 
    2278             :         DEBUGFUNC("ixgbe_setup_fc_X550em");
    2279             : 
    2280             :         /* Validate the requested mode */
    2281           0 :         if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
    2282             :                 DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
    2283             :                 ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
    2284           0 :                 goto out;
    2285             :         }
    2286             : 
    2287             :         /* 10gig parts do not have a word in the EEPROM to determine the
    2288             :          * default flow control setting, so we explicitly set it to full.
    2289             :          */
    2290           0 :         if (hw->fc.requested_mode == ixgbe_fc_default)
    2291           0 :                 hw->fc.requested_mode = ixgbe_fc_full;
    2292             : 
    2293             :         /* Determine PAUSE and ASM_DIR bits. */
    2294           0 :         switch (hw->fc.requested_mode) {
    2295             :         case ixgbe_fc_none:
    2296             :                 pause = 0;
    2297             :                 asm_dir = 0;
    2298           0 :                 break;
    2299             :         case ixgbe_fc_tx_pause:
    2300             :                 pause = 0;
    2301             :                 asm_dir = 1;
    2302           0 :                 break;
    2303             :         case ixgbe_fc_rx_pause:
    2304             :                 /* Rx Flow control is enabled and Tx Flow control is
    2305             :                  * disabled by software override. Since there really
    2306             :                  * isn't a way to advertise that we are capable of RX
    2307             :                  * Pause ONLY, we will advertise that we support both
    2308             :                  * symmetric and asymmetric Rx PAUSE, as such we fall
    2309             :                  * through to the fc_full statement.  Later, we will
    2310             :                  * disable the adapter's ability to send PAUSE frames.
    2311             :                  */
    2312             :         case ixgbe_fc_full:
    2313             :                 pause = 1;
    2314             :                 asm_dir = 1;
    2315           0 :                 break;
    2316             :         default:
    2317             :                 DEBUGOUT("Flow control param set incorrectly\n");
    2318             :                 ret_val = IXGBE_ERR_CONFIG;
    2319           0 :                 goto out;
    2320             :         }
    2321             : 
    2322           0 :         if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
    2323           0 :                 ret_val = ixgbe_read_iosf_sb_reg_x550(hw,
    2324           0 :                         IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
    2325             :                         IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
    2326           0 :                 if (ret_val != IXGBE_SUCCESS)
    2327             :                         goto out;
    2328           0 :                 reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
    2329             :                         IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
    2330           0 :                 if (pause)
    2331           0 :                         reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
    2332           0 :                 if (asm_dir)
    2333           0 :                         reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
    2334           0 :                 ret_val = ixgbe_write_iosf_sb_reg_x550(hw,
    2335           0 :                         IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
    2336           0 :                         IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
    2337             : 
    2338             :                 /* This device does not fully support AN. */
    2339           0 :                 hw->fc.disable_fc_autoneg = TRUE;
    2340           0 :         }
    2341             : 
    2342             : out:
    2343           0 :         return ret_val;
    2344           0 : }
    2345             : 
    2346             : /**
    2347             :  * ixgbe_set_mux - Set mux for port 1 access with CS4227
    2348             :  * @hw: pointer to hardware structure
    2349             :  * @state: set mux if 1, clear if 0
    2350             :  */
    2351           0 : void ixgbe_set_mux(struct ixgbe_hw *hw, uint8_t state)
    2352             : {
    2353             :         uint32_t esdp;
    2354             : 
    2355           0 :         if (!hw->bus.lan_id)
    2356           0 :                 return;
    2357           0 :         esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
    2358           0 :         if (state)
    2359           0 :                 esdp |= IXGBE_ESDP_SDP1;
    2360             :         else
    2361           0 :                 esdp &= ~IXGBE_ESDP_SDP1;
    2362           0 :         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
    2363           0 :         IXGBE_WRITE_FLUSH(hw);
    2364           0 : }
    2365             : 
    2366             : /**
    2367             :  *  ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore
    2368             :  *  @hw: pointer to hardware structure
    2369             :  *  @mask: Mask to specify which semaphore to acquire
    2370             :  *
    2371             :  *  Acquires the SWFW semaphore and sets the I2C MUX
    2372             :  **/
    2373           0 : int32_t ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask)
    2374             : {
    2375             :         int32_t status;
    2376             : 
    2377             :         DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em");
    2378             : 
    2379           0 :         status = ixgbe_acquire_swfw_sync_X540(hw, mask);
    2380           0 :         if (status)
    2381           0 :                 return status;
    2382             : 
    2383           0 :         if (mask & IXGBE_GSSR_I2C_MASK)
    2384           0 :                 ixgbe_set_mux(hw, 1);
    2385             : 
    2386           0 :         return IXGBE_SUCCESS;
    2387           0 : }
    2388             : 
    2389             : /**
    2390             :  *  ixgbe_release_swfw_sync_X550em - Release SWFW semaphore
    2391             :  *  @hw: pointer to hardware structure
    2392             :  *  @mask: Mask to specify which semaphore to release
    2393             :  *
    2394             :  *  Releases the SWFW semaphore and sets the I2C MUX
    2395             :  **/
    2396           0 : void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, uint32_t mask)
    2397             : {
    2398             :         DEBUGFUNC("ixgbe_release_swfw_sync_X550em");
    2399             : 
    2400           0 :         if (mask & IXGBE_GSSR_I2C_MASK)
    2401           0 :                 ixgbe_set_mux(hw, 0);
    2402             : 
    2403           0 :         ixgbe_release_swfw_sync_X540(hw, mask);
    2404           0 : }
    2405             : 
    2406             : /**
    2407             :  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
    2408             :  * @hw: pointer to hardware structure
    2409             :  *
    2410             :  * Handle external Base T PHY interrupt. If high temperature
    2411             :  * failure alarm then return error, else if link status change
    2412             :  * then setup internal/external PHY link
    2413             :  *
    2414             :  * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
    2415             :  * failure alarm, else return PHY access status.
    2416             :  */
    2417           0 : int32_t ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
    2418             : {
    2419           0 :         bool lsc;
    2420             :         uint32_t status;
    2421             : 
    2422           0 :         status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
    2423             : 
    2424           0 :         if (status != IXGBE_SUCCESS)
    2425           0 :                 return status;
    2426             : 
    2427           0 :         if (lsc && hw->phy.ops.setup_internal_link)
    2428           0 :                 return hw->phy.ops.setup_internal_link(hw);
    2429             : 
    2430           0 :         return IXGBE_SUCCESS;
    2431           0 : }
    2432             : 
    2433             : /**
    2434             :  * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
    2435             :  * @hw: pointer to hardware structure
    2436             :  * @speed: new link speed
    2437             :  * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
    2438             :  *
    2439             :  * Setup internal/external PHY link speed based on link speed, then set
    2440             :  * external PHY auto advertised link speed.
    2441             :  *
    2442             :  * Returns error status for any failure
    2443             :  **/
    2444           0 : int32_t ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
    2445             :                                       ixgbe_link_speed speed,
    2446             :                                       bool autoneg_wait_to_complete)
    2447             : {
    2448             :         int32_t status;
    2449           0 :         ixgbe_link_speed force_speed;
    2450             : 
    2451             :         DEBUGFUNC("ixgbe_setup_mac_link_t_X550em");
    2452             : 
    2453             :         /* Setup internal/external PHY link speed to iXFI (10G), unless
    2454             :          * only 1G is auto advertised then setup KX link.
    2455             :          */
    2456           0 :         if (speed & IXGBE_LINK_SPEED_10GB_FULL)
    2457           0 :                 force_speed = IXGBE_LINK_SPEED_10GB_FULL;
    2458             :         else
    2459           0 :                 force_speed = IXGBE_LINK_SPEED_1GB_FULL;
    2460             : 
    2461             :         /* If internal link mode is XFI, then setup XFI internal link. */
    2462           0 :         if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
    2463           0 :                 status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
    2464             : 
    2465           0 :                 if (status != IXGBE_SUCCESS)
    2466           0 :                         return status;
    2467             :         }
    2468             : 
    2469           0 :         return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete);
    2470           0 : }
    2471             : 
    2472             : /**
    2473             :  * ixgbe_check_link_t_X550em - Determine link and speed status
    2474             :  * @hw: pointer to hardware structure
    2475             :  * @speed: pointer to link speed
    2476             :  * @link_up: TRUE when link is up
    2477             :  * @link_up_wait_to_complete: bool used to wait for link up or not
    2478             :  *
    2479             :  * Check that both the MAC and X557 external PHY have link.
    2480             :  **/
    2481           0 : int32_t ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
    2482             :                                   bool *link_up, bool link_up_wait_to_complete)
    2483             : {
    2484             :         uint32_t status;
    2485           0 :         uint16_t autoneg_status;
    2486             : 
    2487           0 :         if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
    2488           0 :                 return IXGBE_ERR_CONFIG;
    2489             : 
    2490           0 :         status = ixgbe_check_mac_link_generic(hw, speed, link_up,
    2491             :                                               link_up_wait_to_complete);
    2492             : 
    2493             :         /* If check link fails or MAC link is not up, then return */
    2494           0 :         if (status != IXGBE_SUCCESS || !(*link_up))
    2495           0 :                 return status;
    2496             : 
    2497             :         /* MAC link is up, so check external PHY link.
    2498             :          * Read this twice back to back to indicate current status.
    2499             :          */
    2500           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
    2501             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    2502             :                                       &autoneg_status);
    2503             : 
    2504           0 :         if (status != IXGBE_SUCCESS)
    2505           0 :                 return status;
    2506             : 
    2507           0 :         status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
    2508             :                                       IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
    2509             :                                       &autoneg_status);
    2510             : 
    2511           0 :         if (status != IXGBE_SUCCESS)
    2512           0 :                 return status;
    2513             : 
    2514             :         /* If external PHY link is not up, then indicate link not up */
    2515           0 :         if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
    2516           0 :                 *link_up = FALSE;
    2517             : 
    2518           0 :         return IXGBE_SUCCESS;
    2519           0 : }
    2520             : 
    2521             : /**
    2522             :  *  ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
    2523             :  *  @hw: pointer to hardware structure
    2524             :  **/
    2525           0 : int32_t ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
    2526             : {
    2527             :         int32_t status;
    2528             : 
    2529           0 :         status = ixgbe_reset_phy_generic(hw);
    2530             : 
    2531           0 :         if (status != IXGBE_SUCCESS)
    2532           0 :                 return status;
    2533             : 
    2534             :         /* Configure Link Status Alarm and Temperature Threshold interrupts */
    2535           0 :         return ixgbe_enable_lasi_ext_t_x550em(hw);
    2536           0 : }
    2537             : 
    2538             : /**
    2539             :  *  ixgbe_led_on_t_X550em - Turns on the software controllable LEDs.
    2540             :  *  @hw: pointer to hardware structure
    2541             :  *  @led_idx: led number to turn on
    2542             :  **/
    2543           0 : int32_t ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx)
    2544             : {
    2545           0 :         uint16_t phy_data;
    2546             : 
    2547             :         DEBUGFUNC("ixgbe_led_on_t_X550em");
    2548             : 
    2549           0 :         if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
    2550           0 :                 return IXGBE_ERR_PARAM;
    2551             : 
    2552             :         /* To turn on the LED, set mode to ON. */
    2553           0 :         hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
    2554             :                              IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
    2555           0 :         phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
    2556           0 :         hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
    2557             :                               IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
    2558             : 
    2559           0 :         return IXGBE_SUCCESS;
    2560           0 : }
    2561             : 
    2562             : /**
    2563             :  *  ixgbe_led_off_t_X550em - Turns off the software controllable LEDs.
    2564             :  *  @hw: pointer to hardware structure
    2565             :  *  @led_idx: led number to turn off
    2566             :  **/
    2567           0 : int32_t ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, uint32_t led_idx)
    2568             : {
    2569           0 :         uint16_t phy_data;
    2570             : 
    2571             :         DEBUGFUNC("ixgbe_led_off_t_X550em");
    2572             : 
    2573           0 :         if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
    2574           0 :                 return IXGBE_ERR_PARAM;
    2575             : 
    2576             :         /* To turn on the LED, set mode to ON. */
    2577           0 :         hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
    2578             :                              IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
    2579           0 :         phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
    2580           0 :         hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
    2581             :                               IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
    2582             : 
    2583           0 :         return IXGBE_SUCCESS;
    2584           0 : }

Generated by: LCOV version 1.13