Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next...
authorDavid S. Miller <davem@davemloft.net>
Thu, 11 Jun 2015 05:14:14 +0000 (22:14 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 11 Jun 2015 05:14:14 +0000 (22:14 -0700)
Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-06-09

This series contains updates to ixgbe only.

The series adds additional support for x550 support, such as WoL and
auto-negotiation of flow control.  Adds new PHY support (external PHY)
for x550, as well as the new methods/functions needed to support the new
PHY's.  Fixed a bug found in code inspection, where a check was missed
when clearing counters for x550.  Also fixed the init code flow for copper
x550 devices.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c

index 636f9e350162bc58a3ea9fb54c0509934fad8985..ac3ac2a2038666e467fba0abbde554e2b4d98a0e 100644 (file)
@@ -643,6 +643,7 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP         (u32)(1 << 8)
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP         (u32)(1 << 9)
 #define IXGBE_FLAG2_PTP_PPS_ENABLED            (u32)(1 << 10)
+#define IXGBE_FLAG2_PHY_INTERRUPT              (u32)(1 << 11)
 
        /* Tx fast path data */
        int num_tx_queues;
index 824a7ab79ab6bd66580bcdefef23b168f3163e7a..65db69b862fb9d8ce87299b641b3615b5b472a0a 100644 (file)
@@ -1225,7 +1225,7 @@ static struct ixgbe_phy_operations phy_ops_82598 = {
        .setup_link_speed       = &ixgbe_setup_phy_link_speed_generic,
        .read_i2c_sff8472       = &ixgbe_read_i2c_sff8472_82598,
        .read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_82598,
-       .check_overtemp   = &ixgbe_tn_check_overtemp,
+       .check_overtemp         = &ixgbe_tn_check_overtemp,
 };
 
 struct ixgbe_info ixgbe_82598_info = {
@@ -1234,4 +1234,5 @@ struct ixgbe_info ixgbe_82598_info = {
        .mac_ops                = &mac_ops_82598,
        .eeprom_ops             = &eeprom_ops_82598,
        .phy_ops                = &phy_ops_82598,
+       .mvals                  = ixgbe_mvals_8259X,
 };
index e0c363948bf46696df96413304fea826f3e054ce..6b87d963461462cc92885aa057b19adbb18125c0 100644 (file)
@@ -71,7 +71,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
 {
        u32 fwsm, manc, factps;
 
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
        if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
                return false;
 
@@ -79,7 +79,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
        if (!(manc & IXGBE_MANC_RCV_TCO_EN))
                return false;
 
-       factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+       factps = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw));
        if (factps & IXGBE_FACTPS_MNGCG)
                return false;
 
@@ -510,7 +510,7 @@ static void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
        hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
 
        /* Check to see if MNG FW could be enabled */
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
 
        if (((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) &&
            !hw->wol_enabled &&
@@ -2378,4 +2378,5 @@ struct ixgbe_info ixgbe_82599_info = {
        .eeprom_ops             = &eeprom_ops_82599,
        .phy_ops                = &phy_ops_82599,
        .mbx_ops                = &mbx_ops_generic,
+       .mvals                  = ixgbe_mvals_8259X,
 };
index 06d8f3cfa099b74a83534a8fce953efd8d6ac066..4c1c26732b67a211ebab3b307b40a0639929d4d5 100644 (file)
@@ -57,6 +57,11 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
                                                 u16 offset);
 static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
 
+/* Base table for registers values that change by MAC */
+const u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT] = {
+       IXGBE_MVALS_INIT(8259X)
+};
+
 /**
  *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
  *  control
@@ -91,6 +96,8 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
                case IXGBE_DEV_ID_82599_T3_LOM:
                case IXGBE_DEV_ID_X540T:
                case IXGBE_DEV_ID_X540T1:
+               case IXGBE_DEV_ID_X550T:
+               case IXGBE_DEV_ID_X550EM_X_10G_T:
                        supported = true;
                        break;
                default:
@@ -463,7 +470,7 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
                }
        }
 
-       if (hw->mac.type == ixgbe_mac_X540) {
+       if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
                if (hw->phy.id == 0)
                        hw->phy.ops.identify(hw);
                hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, MDIO_MMD_PCS, &i);
@@ -681,7 +688,7 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
        bus->lan_id = bus->func;
 
        /* check for a port swap */
-       reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+       reg = IXGBE_READ_REG(hw, IXGBE_FACTPS(hw));
        if (reg & IXGBE_FACTPS_LFS)
                bus->func ^= 0x1;
 }
@@ -799,7 +806,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
                 * Check for EEPROM present first.
                 * If not present leave as none
                 */
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
                if (eec & IXGBE_EEC_PRES) {
                        eeprom->type = ixgbe_eeprom_spi;
 
@@ -1283,14 +1290,14 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
                return IXGBE_ERR_SWFW_SYNC;
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
        /* Request EEPROM Access */
        eec |= IXGBE_EEC_REQ;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
 
        for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
                if (eec & IXGBE_EEC_GNT)
                        break;
                udelay(5);
@@ -1299,7 +1306,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
        /* Release if grant not acquired */
        if (!(eec & IXGBE_EEC_GNT)) {
                eec &= ~IXGBE_EEC_REQ;
-               IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+               IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
                hw_dbg(hw, "Could not acquire EEPROM grant\n");
 
                hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
@@ -1309,7 +1316,7 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
        /* Setup EEPROM for Read/Write */
        /* Clear CS and SK */
        eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
        udelay(1);
        return 0;
@@ -1333,7 +1340,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
                 * If the SMBI bit is 0 when we read it, then the bit will be
                 * set and we have the semaphore
                 */
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
                if (!(swsm & IXGBE_SWSM_SMBI))
                        break;
                usleep_range(50, 100);
@@ -1353,7 +1360,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
                 * If the SMBI bit is 0 when we read it, then the bit will be
                 * set and we have the semaphore
                 */
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
                if (swsm & IXGBE_SWSM_SMBI) {
                        hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
                        return IXGBE_ERR_EEPROM;
@@ -1362,16 +1369,16 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 
        /* Now get the semaphore between SW/FW through the SWESMBI bit */
        for (i = 0; i < timeout; i++) {
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
 
                /* Set the SW EEPROM semaphore bit to request access */
                swsm |= IXGBE_SWSM_SWESMBI;
-               IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+               IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm);
 
                /* If we set the bit successfully then we got the
                 * semaphore.
                 */
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
                if (swsm & IXGBE_SWSM_SWESMBI)
                        break;
 
@@ -1400,11 +1407,11 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
 {
        u32 swsm;
 
-       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
 
        /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */
        swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI);
-       IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+       IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm);
        IXGBE_WRITE_FLUSH(hw);
 }
 
@@ -1454,15 +1461,15 @@ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
 {
        u32 eec;
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
        /* Toggle CS to flush commands */
        eec |= IXGBE_EEC_CS;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
        udelay(1);
        eec &= ~IXGBE_EEC_CS;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
        udelay(1);
 }
@@ -1480,7 +1487,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
        u32 mask;
        u32 i;
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
        /*
         * Mask is used to shift "count" bits of "data" out to the EEPROM
@@ -1501,7 +1508,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
                else
                        eec &= ~IXGBE_EEC_DI;
 
-               IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+               IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
                IXGBE_WRITE_FLUSH(hw);
 
                udelay(1);
@@ -1518,7 +1525,7 @@ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
 
        /* We leave the "DI" bit set to "0" when we leave this routine. */
        eec &= ~IXGBE_EEC_DI;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
 }
 
@@ -1539,7 +1546,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
         * the value of the "DO" bit.  During this "shifting in" process the
         * "DI" bit should always be clear.
         */
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
        eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
 
@@ -1547,7 +1554,7 @@ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
                data = data << 1;
                ixgbe_raise_eeprom_clk(hw, &eec);
 
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
                eec &= ~(IXGBE_EEC_DI);
                if (eec & IXGBE_EEC_DO)
@@ -1571,7 +1578,7 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
         * (setting the SK bit), then delay
         */
        *eec = *eec | IXGBE_EEC_SK;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec);
        IXGBE_WRITE_FLUSH(hw);
        udelay(1);
 }
@@ -1588,7 +1595,7 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
         * delay
         */
        *eec = *eec & ~IXGBE_EEC_SK;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), *eec);
        IXGBE_WRITE_FLUSH(hw);
        udelay(1);
 }
@@ -1601,19 +1608,19 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
 {
        u32 eec;
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
        eec |= IXGBE_EEC_CS;  /* Pull CS high */
        eec &= ~IXGBE_EEC_SK; /* Lower SCK */
 
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
 
        udelay(1);
 
        /* Stop requesting EEPROM access */
        eec &= ~IXGBE_EEC_REQ;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), eec);
 
        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 
index f21f8a165ec4ff4c104d5ac8aedb385c7f841901..ec015fed8fa7a32795e0bfa0fface796cb6bfaab 100644 (file)
@@ -118,6 +118,8 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw);
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
                             u32 headroom, int strategy);
 
+extern const u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT];
+
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR  0xF8
 #define IXGBE_EMC_INTERNAL_DATA                0x00
 #define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
index 9a1d0f142b091c3cecb06ce65ffac1d3c8e6bf1a..ec7b2324b77b42489d9892de6b785ab7ca9936cf 100644 (file)
@@ -207,6 +207,7 @@ static int ixgbe_get_settings(struct net_device *netdev,
        switch (adapter->hw.phy.type) {
        case ixgbe_phy_tn:
        case ixgbe_phy_aq:
+       case ixgbe_phy_x550em_ext_t:
        case ixgbe_phy_cu_unknown:
                ecmd->supported |= SUPPORTED_TP;
                ecmd->advertising |= ADVERTISED_TP;
@@ -470,16 +471,16 @@ static void ixgbe_get_regs(struct net_device *netdev,
        regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_TCPTIMER);
 
        /* NVM Register */
-       regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_EEC);
+       regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
        regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_EERD);
-       regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_FLA);
+       regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_FLA(hw));
        regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_EEMNGCTL);
        regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_EEMNGDATA);
        regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_FLMNGCTL);
        regs_buff[14] = IXGBE_READ_REG(hw, IXGBE_FLMNGDATA);
        regs_buff[15] = IXGBE_READ_REG(hw, IXGBE_FLMNGCNT);
        regs_buff[16] = IXGBE_READ_REG(hw, IXGBE_FLOP);
-       regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC);
+       regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC(hw));
 
        /* Interrupt */
        /* don't read EICR because it can clear interrupt causes, instead
index 23d82b34314e110ccd5dca1d52b330b25a708126..3bf2f3cfd9f6d9f25e17a5dcc37386f0e1831bd7 100644 (file)
@@ -81,6 +81,8 @@ const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
                                "Copyright (c) 1999-2014 Intel Corporation.";
 
+static const char ixgbe_overheat_msg[] = "Network adapter has been stopped because it has over heated. Restart the computer. If the problem persists, power off the system and replace the adapter";
+
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
        [board_82598]           = &ixgbe_82598_info,
        [board_82599]           = &ixgbe_82599_info,
@@ -131,6 +133,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550T), board_X550},
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4), board_X550EM_x},
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x},
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x},
        /* required last entry */
        {0, }
 };
@@ -2366,7 +2369,7 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
                 *  - We may have missed the interrupt so always have to
                 *    check if we  got a LSC
                 */
-               if (!(eicr & IXGBE_EICR_GPI_SDP0) &&
+               if (!(eicr & IXGBE_EICR_GPI_SDP0_8259X) &&
                    !(eicr & IXGBE_EICR_LSC))
                        return;
 
@@ -2386,14 +2389,13 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
 
                break;
        default:
-               if (!(eicr & IXGBE_EICR_GPI_SDP0))
+               if (adapter->hw.mac.type >= ixgbe_mac_X540)
+                       return;
+               if (!(eicr & IXGBE_EICR_GPI_SDP0(hw)))
                        return;
                break;
        }
-       e_crit(drv,
-              "Network adapter has been stopped because it has over heated. "
-              "Restart the computer. If the problem persists, "
-              "power off the system and replace the adapter\n");
+       e_crit(drv, "%s\n", ixgbe_overheat_msg);
 
        adapter->interrupt_event = 0;
 }
@@ -2403,15 +2405,17 @@ static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
        struct ixgbe_hw *hw = &adapter->hw;
 
        if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) &&
-           (eicr & IXGBE_EICR_GPI_SDP1)) {
+           (eicr & IXGBE_EICR_GPI_SDP1(hw))) {
                e_crit(probe, "Fan has stopped, replace the adapter\n");
                /* write to clear the interrupt */
-               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1(hw));
        }
 }
 
 static void ixgbe_check_overtemp_event(struct ixgbe_adapter *adapter, u32 eicr)
 {
+       struct ixgbe_hw *hw = &adapter->hw;
+
        if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE))
                return;
 
@@ -2421,7 +2425,8 @@ static void ixgbe_check_overtemp_event(struct ixgbe_adapter *adapter, u32 eicr)
                 * Need to check link state so complete overtemp check
                 * on service task
                 */
-               if (((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC)) &&
+               if (((eicr & IXGBE_EICR_GPI_SDP0(hw)) ||
+                    (eicr & IXGBE_EICR_LSC)) &&
                    (!test_bit(__IXGBE_DOWN, &adapter->state))) {
                        adapter->interrupt_event = eicr;
                        adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
@@ -2437,28 +2442,46 @@ static void ixgbe_check_overtemp_event(struct ixgbe_adapter *adapter, u32 eicr)
                return;
        }
 
-       e_crit(drv,
-              "Network adapter has been stopped because it has over heated. "
-              "Restart the computer. If the problem persists, "
-              "power off the system and replace the adapter\n");
+       e_crit(drv, "%s\n", ixgbe_overheat_msg);
+}
+
+static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
+{
+       switch (hw->mac.type) {
+       case ixgbe_mac_82598EB:
+               if (hw->phy.type == ixgbe_phy_nl)
+                       return true;
+               return false;
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X550EM_x:
+               switch (hw->mac.ops.get_media_type(hw)) {
+               case ixgbe_media_type_fiber:
+               case ixgbe_media_type_fiber_qsfp:
+                       return true;
+               default:
+                       return false;
+               }
+       default:
+               return false;
+       }
 }
 
 static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
 {
        struct ixgbe_hw *hw = &adapter->hw;
 
-       if (eicr & IXGBE_EICR_GPI_SDP2) {
+       if (eicr & IXGBE_EICR_GPI_SDP2(hw)) {
                /* Clear the interrupt */
-               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2(hw));
                if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
                        adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
                        ixgbe_service_event_schedule(adapter);
                }
        }
 
-       if (eicr & IXGBE_EICR_GPI_SDP1) {
+       if (eicr & IXGBE_EICR_GPI_SDP1(hw)) {
                /* Clear the interrupt */
-               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1(hw));
                if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
                        adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
                        ixgbe_service_event_schedule(adapter);
@@ -2543,6 +2566,7 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
 static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
                                    bool flush)
 {
+       struct ixgbe_hw *hw = &adapter->hw;
        u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
 
        /* don't reenable LSC while waiting for link */
@@ -2552,7 +2576,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
        if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
                switch (adapter->hw.mac.type) {
                case ixgbe_mac_82599EB:
-                       mask |= IXGBE_EIMS_GPI_SDP0;
+                       mask |= IXGBE_EIMS_GPI_SDP0(hw);
                        break;
                case ixgbe_mac_X540:
                case ixgbe_mac_X550:
@@ -2563,15 +2587,17 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
                        break;
                }
        if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
-               mask |= IXGBE_EIMS_GPI_SDP1;
+               mask |= IXGBE_EIMS_GPI_SDP1(hw);
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
-               mask |= IXGBE_EIMS_GPI_SDP1;
-               mask |= IXGBE_EIMS_GPI_SDP2;
+               mask |= IXGBE_EIMS_GPI_SDP1(hw);
+               mask |= IXGBE_EIMS_GPI_SDP2(hw);
                /* fall through */
        case ixgbe_mac_X540:
        case ixgbe_mac_X550:
        case ixgbe_mac_X550EM_x:
+               if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t)
+                       mask |= IXGBE_EICR_GPI_SDP0_X540;
                mask |= IXGBE_EIMS_ECC;
                mask |= IXGBE_EIMS_MAILBOX;
                break;
@@ -2626,6 +2652,13 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
        case ixgbe_mac_X540:
        case ixgbe_mac_X550:
        case ixgbe_mac_X550EM_x:
+               if (hw->phy.type == ixgbe_phy_x550em_ext_t &&
+                   (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
+                       adapter->flags2 |= IXGBE_FLAG2_PHY_INTERRUPT;
+                       ixgbe_service_event_schedule(adapter);
+                       IXGBE_WRITE_REG(hw, IXGBE_EICR,
+                                       IXGBE_EICR_GPI_SDP0_X540);
+               }
                if (eicr & IXGBE_EICR_ECC) {
                        e_info(link, "Received ECC Err, initiating reset\n");
                        adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
@@ -4703,32 +4736,6 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
        ixgbe_configure_dfwd(adapter);
 }
 
-static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
-{
-       switch (hw->phy.type) {
-       case ixgbe_phy_sfp_avago:
-       case ixgbe_phy_sfp_ftl:
-       case ixgbe_phy_sfp_intel:
-       case ixgbe_phy_sfp_unknown:
-       case ixgbe_phy_sfp_passive_tyco:
-       case ixgbe_phy_sfp_passive_unknown:
-       case ixgbe_phy_sfp_active_unknown:
-       case ixgbe_phy_sfp_ftl_active:
-       case ixgbe_phy_qsfp_passive_unknown:
-       case ixgbe_phy_qsfp_active_unknown:
-       case ixgbe_phy_qsfp_intel:
-       case ixgbe_phy_qsfp_unknown:
-       /* ixgbe_phy_none is set when no SFP module is present */
-       case ixgbe_phy_none:
-               return true;
-       case ixgbe_phy_nl:
-               if (hw->mac.type == ixgbe_mac_82598EB)
-                       return true;
-       default:
-               return false;
-       }
-}
-
 /**
  * ixgbe_sfp_link_config - set up SFP+ link
  * @adapter: pointer to private adapter struct
@@ -4833,7 +4840,7 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
        if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
                switch (adapter->hw.mac.type) {
                case ixgbe_mac_82599EB:
-                       gpie |= IXGBE_SDP0_GPIEN;
+                       gpie |= IXGBE_SDP0_GPIEN_8259X;
                        break;
                case ixgbe_mac_X540:
                        gpie |= IXGBE_EIMS_TS;
@@ -4845,11 +4852,11 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
 
        /* Enable fan failure interrupt */
        if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
-               gpie |= IXGBE_SDP1_GPIEN;
+               gpie |= IXGBE_SDP1_GPIEN(hw);
 
        if (hw->mac.type == ixgbe_mac_82599EB) {
-               gpie |= IXGBE_SDP1_GPIEN;
-               gpie |= IXGBE_SDP2_GPIEN;
+               gpie |= IXGBE_SDP1_GPIEN_8259X;
+               gpie |= IXGBE_SDP2_GPIEN_8259X;
        }
 
        IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
@@ -4873,6 +4880,9 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
        if (hw->mac.ops.enable_tx_laser)
                hw->mac.ops.enable_tx_laser(hw);
 
+       if (hw->phy.ops.set_phy_power)
+               hw->phy.ops.set_phy_power(hw, true);
+
        smp_mb__before_atomic();
        clear_bit(__IXGBE_DOWN, &adapter->state);
        ixgbe_napi_enable_all(adapter);
@@ -4992,6 +5002,13 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
 
        if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state))
                ixgbe_ptp_reset(adapter);
+
+       if (hw->phy.ops.set_phy_power) {
+               if (!netif_running(adapter->netdev) && !adapter->wol)
+                       hw->phy.ops.set_phy_power(hw, false);
+               else
+                       hw->phy.ops.set_phy_power(hw, true);
+       }
 }
 
 /**
@@ -5260,7 +5277,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
                        adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
                break;
        case ixgbe_mac_X540:
-               fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+               fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
                if (fwsm & IXGBE_FWSM_TS_ENABLED)
                        adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
                break;
@@ -5672,6 +5689,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 static int ixgbe_open(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       struct ixgbe_hw *hw = &adapter->hw;
        int err, queues;
 
        /* disallow open during test */
@@ -5729,6 +5747,8 @@ err_set_queues:
        ixgbe_free_irq(adapter);
 err_req_irq:
        ixgbe_free_all_rx_resources(adapter);
+       if (hw->phy.ops.set_phy_power && !adapter->wol)
+               hw->phy.ops.set_phy_power(&adapter->hw, false);
 err_setup_rx:
        ixgbe_free_all_tx_resources(adapter);
 err_setup_tx:
@@ -5889,6 +5909,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
        }
 
        *enable_wake = !!wufc;
+       if (hw->phy.ops.set_phy_power && !*enable_wake)
+               hw->phy.ops.set_phy_power(hw, false);
 
        ixgbe_release_hw_control(adapter);
 
@@ -6718,6 +6740,26 @@ static void ixgbe_service_timer(unsigned long data)
        ixgbe_service_event_schedule(adapter);
 }
 
+static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 status;
+
+       if (!(adapter->flags2 & IXGBE_FLAG2_PHY_INTERRUPT))
+               return;
+
+       adapter->flags2 &= ~IXGBE_FLAG2_PHY_INTERRUPT;
+
+       if (!hw->phy.ops.handle_lasi)
+               return;
+
+       status = hw->phy.ops.handle_lasi(&adapter->hw);
+       if (status != IXGBE_ERR_OVERTEMP)
+               return;
+
+       e_crit(drv, "%s\n", ixgbe_overheat_msg);
+}
+
 static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
 {
        if (!(adapter->flags2 & IXGBE_FLAG2_RESET_REQUESTED))
@@ -6759,6 +6801,7 @@ static void ixgbe_service_task(struct work_struct *work)
                return;
        }
        ixgbe_reset_subtask(adapter);
+       ixgbe_phy_interrupt_subtask(adapter);
        ixgbe_sfp_detection_subtask(adapter);
        ixgbe_sfp_link_config_subtask(adapter);
        ixgbe_check_overtemp_subtask(adapter);
@@ -8291,6 +8334,10 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
                break;
        case IXGBE_DEV_ID_X540T:
        case IXGBE_DEV_ID_X540T1:
+       case IXGBE_DEV_ID_X550T:
+       case IXGBE_DEV_ID_X550EM_X_KX4:
+       case IXGBE_DEV_ID_X550EM_X_KR:
+       case IXGBE_DEV_ID_X550EM_X_10G_T:
                /* check eeprom to see if enabled wol */
                if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
                    ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
@@ -8431,10 +8478,11 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Setup hw api */
        memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
        hw->mac.type  = ii->mac;
+       hw->mvals     = ii->mvals;
 
        /* EEPROM */
        memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops));
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
        if (ixgbe_removed(hw->hw_addr)) {
                err = -EIO;
                goto err_ioremap;
index af828f89419f8dc94ccde1b2c18c5ec64f7e3bd8..526a20bf74888b7c770a9381d63cc7a6a711bd09 100644 (file)
@@ -347,6 +347,7 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
        case TN1010_PHY_ID:
                phy_type = ixgbe_phy_tn;
                break;
+       case X550_PHY_ID:
        case X540_PHY_ID:
                phy_type = ixgbe_phy_aq;
                break;
@@ -356,6 +357,9 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
        case ATH_PHY_ID:
                phy_type = ixgbe_phy_nl;
                break;
+       case X557_PHY_ID:
+               phy_type = ixgbe_phy_x550em_ext_t;
+               break;
        default:
                phy_type = ixgbe_phy_unknown;
                break;
@@ -1348,6 +1352,9 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
                return IXGBE_ERR_SFP_NOT_PRESENT;
        }
 
+       /* LAN ID is needed for sfp_type determination */
+       hw->mac.ops.set_lan_id(hw);
+
        status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
                                             &identifier);
 
@@ -1361,9 +1368,6 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 
        hw->phy.id = identifier;
 
-       /* LAN ID is needed for sfp_type determination */
-       hw->mac.ops.set_lan_id(hw);
-
        status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP,
                                             &comp_codes_10g);
 
@@ -1793,7 +1797,7 @@ fail:
  **/
 static void ixgbe_i2c_start(struct ixgbe_hw *hw)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
 
        /* Start condition must begin with data and clock high */
        ixgbe_set_i2c_data(hw, &i2cctl, 1);
@@ -1822,7 +1826,7 @@ static void ixgbe_i2c_start(struct ixgbe_hw *hw)
  **/
 static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
 
        /* Stop condition must begin with data low and clock high */
        ixgbe_set_i2c_data(hw, &i2cctl, 0);
@@ -1880,9 +1884,9 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
        }
 
        /* Release SDA line (set high) */
-       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
-       i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw);
-       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl);
+       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+       i2cctl |= IXGBE_I2C_DATA_OUT(hw);
+       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl);
        IXGBE_WRITE_FLUSH(hw);
 
        return status;
@@ -1898,7 +1902,7 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
 {
        s32 status = 0;
        u32 i = 0;
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
        u32 timeout = 10;
        bool ack = true;
 
@@ -1911,7 +1915,7 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
        /* Poll for ACK.  Note that ACK in I2C spec is
         * transition from 1 to 0 */
        for (i = 0; i < timeout; i++) {
-               i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+               i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
                ack = ixgbe_get_i2c_data(hw, &i2cctl);
 
                udelay(1);
@@ -1941,14 +1945,14 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
  **/
 static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
 
        ixgbe_raise_i2c_clk(hw, &i2cctl);
 
        /* Minimum high period of clock is 4us */
        udelay(IXGBE_I2C_T_HIGH);
 
-       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
        *data = ixgbe_get_i2c_data(hw, &i2cctl);
 
        ixgbe_lower_i2c_clk(hw, &i2cctl);
@@ -1969,7 +1973,7 @@ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
 static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
 {
        s32 status;
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
 
        status = ixgbe_set_i2c_data(hw, &i2cctl, data);
        if (status == 0) {
@@ -2005,14 +2009,14 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
        u32 i2cctl_r = 0;
 
        for (i = 0; i < timeout; i++) {
-               *i2cctl |= IXGBE_I2C_CLK_OUT_BY_MAC(hw);
-               IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl);
+               *i2cctl |= IXGBE_I2C_CLK_OUT(hw);
+               IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
                IXGBE_WRITE_FLUSH(hw);
                /* SCL rise time (1000ns) */
                udelay(IXGBE_I2C_T_RISE);
 
-               i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
-               if (i2cctl_r & IXGBE_I2C_CLK_IN_BY_MAC(hw))
+               i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
+               if (i2cctl_r & IXGBE_I2C_CLK_IN(hw))
                        break;
        }
 }
@@ -2027,9 +2031,9 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
 static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
 {
 
-       *i2cctl &= ~IXGBE_I2C_CLK_OUT_BY_MAC(hw);
+       *i2cctl &= ~IXGBE_I2C_CLK_OUT(hw);
 
-       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl);
+       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
        IXGBE_WRITE_FLUSH(hw);
 
        /* SCL fall time (300ns) */
@@ -2047,18 +2051,18 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
 static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
 {
        if (data)
-               *i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw);
+               *i2cctl |= IXGBE_I2C_DATA_OUT(hw);
        else
-               *i2cctl &= ~IXGBE_I2C_DATA_OUT_BY_MAC(hw);
+               *i2cctl &= ~IXGBE_I2C_DATA_OUT(hw);
 
-       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl);
+       IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl);
        IXGBE_WRITE_FLUSH(hw);
 
        /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
        udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA);
 
        /* Verify data was set correctly */
-       *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
        if (data != ixgbe_get_i2c_data(hw, i2cctl)) {
                hw_dbg(hw, "Error - I2C data was not set to %X.\n", data);
                return IXGBE_ERR_I2C;
@@ -2076,7 +2080,7 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
  **/
 static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl)
 {
-       if (*i2cctl & IXGBE_I2C_DATA_IN_BY_MAC(hw))
+       if (*i2cctl & IXGBE_I2C_DATA_IN(hw))
                return true;
        return false;
 }
@@ -2090,7 +2094,7 @@ static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl)
  **/
 static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
 {
-       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw));
+       u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
        u32 i;
 
        ixgbe_i2c_start(hw);
@@ -2137,3 +2141,36 @@ s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
 
        return IXGBE_ERR_OVERTEMP;
 }
+
+/** ixgbe_set_copper_phy_power - Control power for copper phy
+ *  @hw: pointer to hardware structure
+ *  @on: true for on, false for off
+ **/
+s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
+{
+       u32 status;
+       u16 reg;
+
+       /* Bail if we don't have copper phy */
+       if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
+               return 0;
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+       if (status)
+               return status;
+
+       if (on) {
+               reg &= ~IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
+       } else {
+               if (ixgbe_check_reset_blocked(hw))
+                       return 0;
+               reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
+       }
+
+       status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+       return status;
+}
index 43464388128787116f4c1f6a37943f946fd9cdab..e45988c4dad556e9b31195f2112de3a44fcb35ab 100644 (file)
@@ -145,6 +145,7 @@ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
                                           u16 *firmware_version);
 
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
+s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on);
 s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
index dd6ba5916dfe002b528684db30eb23c847829c2c..b6f424f3b1a8388da48c6038faae16922e773e7a 100644 (file)
 #define IXGBE_DEV_ID_X550_VF           0x1565
 #define IXGBE_DEV_ID_X550EM_X_VF       0x15A8
 
+#define IXGBE_CAT(r, m)        IXGBE_##r##_##m
+
+#define IXGBE_BY_MAC(_hw, r)   ((_hw)->mvals[IXGBE_CAT(r, IDX)])
+
 /* General Registers */
 #define IXGBE_CTRL      0x00000
 #define IXGBE_STATUS    0x00008
 #define IXGBE_CTRL_EXT  0x00018
 #define IXGBE_ESDP      0x00020
 #define IXGBE_EODSDP    0x00028
-#define IXGBE_I2CCTL_BY_MAC(_hw)((((_hw)->mac.type >= ixgbe_mac_X550) ? \
-                                       0x15F5C : 0x00028))
+
+#define IXGBE_I2CCTL_8259X     0x00028
+#define IXGBE_I2CCTL_X540      IXGBE_I2CCTL_8259X
+#define IXGBE_I2CCTL_X550      0x15F5C
+#define IXGBE_I2CCTL_X550EM_x  IXGBE_I2CCTL_X550
+#define IXGBE_I2CCTL_X550EM_a  IXGBE_I2CCTL_X550
+#define IXGBE_I2CCTL(_hw)      IXGBE_BY_MAC((_hw), I2CCTL)
+
 #define IXGBE_LEDCTL    0x00200
 #define IXGBE_FRTIMER   0x00048
 #define IXGBE_TCPTIMER  0x0004C
 #define IXGBE_EXVET     0x05078
 
 /* NVM Registers */
-#define IXGBE_EEC       0x10010
+#define IXGBE_EEC_8259X                0x10010
+#define IXGBE_EEC_X540         IXGBE_EEC_8259X
+#define IXGBE_EEC_X550         IXGBE_EEC_8259X
+#define IXGBE_EEC_X550EM_x     IXGBE_EEC_8259X
+#define IXGBE_EEC_X550EM_a     0x15FF8
+#define IXGBE_EEC(_hw)         IXGBE_BY_MAC((_hw), EEC)
 #define IXGBE_EERD      0x10014
 #define IXGBE_EEWR      0x10018
-#define IXGBE_FLA       0x1001C
+#define IXGBE_FLA_8259X                0x1001C
+#define IXGBE_FLA_X540         IXGBE_FLA_8259X
+#define IXGBE_FLA_X550         IXGBE_FLA_8259X
+#define IXGBE_FLA_X550EM_x     IXGBE_FLA_8259X
+#define IXGBE_FLA_X550EM_a     0x15F6C
+#define IXGBE_FLA(_hw)         IXGBE_BY_MAC((_hw), FLA)
 #define IXGBE_EEMNGCTL  0x10110
 #define IXGBE_EEMNGDATA 0x10114
 #define IXGBE_FLMNGCTL  0x10118
 #define IXGBE_FLMNGDATA 0x1011C
 #define IXGBE_FLMNGCNT  0x10120
 #define IXGBE_FLOP      0x1013C
-#define IXGBE_GRC       0x10200
+#define IXGBE_GRC_8259X                0x10200
+#define IXGBE_GRC_X540         IXGBE_GRC_8259X
+#define IXGBE_GRC_X550         IXGBE_GRC_8259X
+#define IXGBE_GRC_X550EM_x     IXGBE_GRC_8259X
+#define IXGBE_GRC_X550EM_a     0x15F64
+#define IXGBE_GRC(_hw)         IXGBE_BY_MAC((_hw), GRC)
+
+#define IXGBE_SRAMREL_8259X    0x10210
+#define IXGBE_SRAMREL_X540     IXGBE_SRAMREL_8259X
+#define IXGBE_SRAMREL_X550     IXGBE_SRAMREL_8259X
+#define IXGBE_SRAMREL_X550EM_x IXGBE_SRAMREL_8259X
+#define IXGBE_SRAMREL_X550EM_a 0x15F6C
+#define IXGBE_SRAMREL(_hw)     IXGBE_BY_MAC((_hw), SRAMREL)
 
 /* General Receive Control */
 #define IXGBE_GRC_MNG  0x00000001 /* Manageability Enable */
 #define IXGBE_VPDDIAG1  0x10208
 
 /* I2CCTL Bit Masks */
-#define IXGBE_I2C_CLK_IN_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \
-                                       0x00004000 : 0x00000001)
-#define IXGBE_I2C_CLK_OUT_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \
-                                       0x00000200 : 0x00000002)
-#define IXGBE_I2C_DATA_IN_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \
-                                       0x00001000 : 0x00000004)
-#define IXGBE_I2C_DATA_OUT_BY_MAC(_hw)(((_hw)->mac.type) >= ixgbe_mac_X550 ? \
-                                       0x00000400 : 0x00000008)
+#define IXGBE_I2C_CLK_IN_8259X         0x00000001
+#define IXGBE_I2C_CLK_IN_X540          IXGBE_I2C_CLK_IN_8259X
+#define IXGBE_I2C_CLK_IN_X550          0x00004000
+#define IXGBE_I2C_CLK_IN_X550EM_x      IXGBE_I2C_CLK_IN_X550
+#define IXGBE_I2C_CLK_IN_X550EM_a      IXGBE_I2C_CLK_IN_X550
+#define IXGBE_I2C_CLK_IN(_hw)          IXGBE_BY_MAC((_hw), I2C_CLK_IN)
+
+#define IXGBE_I2C_CLK_OUT_8259X                0x00000002
+#define IXGBE_I2C_CLK_OUT_X540         IXGBE_I2C_CLK_OUT_8259X
+#define IXGBE_I2C_CLK_OUT_X550         0x00000200
+#define IXGBE_I2C_CLK_OUT_X550EM_x     IXGBE_I2C_CLK_OUT_X550
+#define IXGBE_I2C_CLK_OUT_X550EM_a     IXGBE_I2C_CLK_OUT_X550
+#define IXGBE_I2C_CLK_OUT(_hw)         IXGBE_BY_MAC((_hw), I2C_CLK_OUT)
+
+#define IXGBE_I2C_DATA_IN_8259X                0x00000004
+#define IXGBE_I2C_DATA_IN_X540         IXGBE_I2C_DATA_IN_8259X
+#define IXGBE_I2C_DATA_IN_X550         0x00001000
+#define IXGBE_I2C_DATA_IN_X550EM_x     IXGBE_I2C_DATA_IN_X550
+#define IXGBE_I2C_DATA_IN_X550EM_a     IXGBE_I2C_DATA_IN_X550
+#define IXGBE_I2C_DATA_IN(_hw)         IXGBE_BY_MAC((_hw), I2C_DATA_IN)
+
+#define IXGBE_I2C_DATA_OUT_8259X       0x00000008
+#define IXGBE_I2C_DATA_OUT_X540                IXGBE_I2C_DATA_OUT_8259X
+#define IXGBE_I2C_DATA_OUT_X550                0x00000400
+#define IXGBE_I2C_DATA_OUT_X550EM_x    IXGBE_I2C_DATA_OUT_X550
+#define IXGBE_I2C_DATA_OUT_X550EM_a    IXGBE_I2C_DATA_OUT_X550
+#define IXGBE_I2C_DATA_OUT(_hw)                IXGBE_BY_MAC((_hw), I2C_DATA_OUT)
+
+#define IXGBE_I2C_DATA_OE_N_EN_8259X   0
+#define IXGBE_I2C_DATA_OE_N_EN_X540    IXGBE_I2C_DATA_OE_N_EN_8259X
+#define IXGBE_I2C_DATA_OE_N_EN_X550    0x00000800
+#define IXGBE_I2C_DATA_OE_N_EN_X550EM_x        IXGBE_I2C_DATA_OE_N_EN_X550
+#define IXGBE_I2C_DATA_OE_N_EN_X550EM_a        IXGBE_I2C_DATA_OE_N_EN_X550
+#define IXGBE_I2C_DATA_OE_N_EN(_hw)    IXGBE_BY_MAC((_hw), I2C_DATA_OE_N_EN)
+
+#define IXGBE_I2C_BB_EN_8259X          0
+#define IXGBE_I2C_BB_EN_X540           IXGBE_I2C_BB_EN_8259X
+#define IXGBE_I2C_BB_EN_X550           0x00000100
+#define IXGBE_I2C_BB_EN_X550EM_x       IXGBE_I2C_BB_EN_X550
+#define IXGBE_I2C_BB_EN_X550EM_a       IXGBE_I2C_BB_EN_X550
+#define IXGBE_I2C_BB_EN(_hw)           IXGBE_BY_MAC((_hw), I2C_BB_EN)
+
+#define IXGBE_I2C_CLK_OE_N_EN_8259X    0
+#define IXGBE_I2C_CLK_OE_N_EN_X540     IXGBE_I2C_CLK_OE_N_EN_8259X
+#define IXGBE_I2C_CLK_OE_N_EN_X550     0x00002000
+#define IXGBE_I2C_CLK_OE_N_EN_X550EM_x IXGBE_I2C_CLK_OE_N_EN_X550
+#define IXGBE_I2C_CLK_OE_N_EN_X550EM_a IXGBE_I2C_CLK_OE_N_EN_X550
+#define IXGBE_I2C_CLK_OE_N_EN(_hw)      IXGBE_BY_MAC((_hw), I2C_CLK_OE_N_EN)
+
 #define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT     500
 
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR  0xF8
@@ -835,15 +908,36 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_GSCN_1    0x11024
 #define IXGBE_GSCN_2    0x11028
 #define IXGBE_GSCN_3    0x1102C
-#define IXGBE_FACTPS    0x10150
+#define IXGBE_FACTPS_8259X     0x10150
+#define IXGBE_FACTPS_X540      IXGBE_FACTPS_8259X
+#define IXGBE_FACTPS_X550      IXGBE_FACTPS_8259X
+#define IXGBE_FACTPS_X550EM_x  IXGBE_FACTPS_8259X
+#define IXGBE_FACTPS_X550EM_a  0x15FEC
+#define IXGBE_FACTPS(_hw)      IXGBE_BY_MAC((_hw), FACTPS)
+
 #define IXGBE_PCIEANACTL  0x11040
-#define IXGBE_SWSM      0x10140
-#define IXGBE_FWSM      0x10148
+#define IXGBE_SWSM_8259X       0x10140
+#define IXGBE_SWSM_X540                IXGBE_SWSM_8259X
+#define IXGBE_SWSM_X550                IXGBE_SWSM_8259X
+#define IXGBE_SWSM_X550EM_x    IXGBE_SWSM_8259X
+#define IXGBE_SWSM_X550EM_a    0x15F70
+#define IXGBE_SWSM(_hw)                IXGBE_BY_MAC((_hw), SWSM)
+#define IXGBE_FWSM_8259X       0x10148
+#define IXGBE_FWSM_X540                IXGBE_FWSM_8259X
+#define IXGBE_FWSM_X550                IXGBE_FWSM_8259X
+#define IXGBE_FWSM_X550EM_x    IXGBE_FWSM_8259X
+#define IXGBE_FWSM_X550EM_a    0x15F74
+#define IXGBE_FWSM(_hw)                IXGBE_BY_MAC((_hw), FWSM)
 #define IXGBE_GSSR      0x10160
 #define IXGBE_MREVID    0x11064
 #define IXGBE_DCA_ID    0x11070
 #define IXGBE_DCA_CTRL  0x11074
-#define IXGBE_SWFW_SYNC IXGBE_GSSR
+#define IXGBE_SWFW_SYNC_8259X          IXGBE_GSSR
+#define IXGBE_SWFW_SYNC_X540           IXGBE_SWFW_SYNC_8259X
+#define IXGBE_SWFW_SYNC_X550           IXGBE_SWFW_SYNC_8259X
+#define IXGBE_SWFW_SYNC_X550EM_x       IXGBE_SWFW_SYNC_8259X
+#define IXGBE_SWFW_SYNC_X550EM_a       0x15F78
+#define IXGBE_SWFW_SYNC(_hw)           IXGBE_BY_MAC((_hw), SWFW_SYNC)
 
 /* PCIe registers 82599-specific */
 #define IXGBE_GCR_EXT           0x11050
@@ -855,14 +949,21 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_PHYDAT_82599      0x11044
 #define IXGBE_PHYCTL_82599      0x11048
 #define IXGBE_PBACLR_82599      0x11068
-#define IXGBE_CIAA_82599        0x11088
-#define IXGBE_CIAD_82599        0x1108C
-#define IXGBE_CIAA_X550         0x11508
-#define IXGBE_CIAD_X550         0x11510
-#define IXGBE_CIAA_BY_MAC(_hw)  ((((_hw)->mac.type >= ixgbe_mac_X550) ? \
-                               IXGBE_CIAA_X550 : IXGBE_CIAA_82599))
-#define IXGBE_CIAD_BY_MAC(_hw)  ((((_hw)->mac.type >= ixgbe_mac_X550) ? \
-                               IXGBE_CIAD_X550 : IXGBE_CIAD_82599))
+
+#define IXGBE_CIAA_8259X       0x11088
+#define IXGBE_CIAA_X540                IXGBE_CIAA_8259X
+#define IXGBE_CIAA_X550                0x11508
+#define IXGBE_CIAA_X550EM_x    IXGBE_CIAA_X550
+#define IXGBE_CIAA_X550EM_a    IXGBE_CIAA_X550
+#define IXGBE_CIAA(_hw)                IXGBE_BY_MAC((_hw), CIAA)
+
+#define IXGBE_CIAD_8259X       0x1108C
+#define IXGBE_CIAD_X540                IXGBE_CIAD_8259X
+#define IXGBE_CIAD_X550                0x11510
+#define IXGBE_CIAD_X550EM_x    IXGBE_CIAD_X550
+#define IXGBE_CIAD_X550EM_a    IXGBE_CIAD_X550
+#define IXGBE_CIAD(_hw)                IXGBE_BY_MAC((_hw), CIAD)
+
 #define IXGBE_PICAUSE           0x110B0
 #define IXGBE_PIENA             0x110B8
 #define IXGBE_CDQ_MBR_82599     0x110B4
@@ -1204,18 +1305,37 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_CONTROL    0x0 /* AUTO_NEG Control Reg */
 #define IXGBE_MDIO_AUTO_NEG_STATUS     0x1 /* AUTO_NEG Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT        0xC800 /* AUTO_NEG Vendor Status Reg */
+#define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */
+#define IXGBE_MDIO_AUTO_NEG_VEN_LSC    0x1 /* AUTO_NEG Vendor Tx LSC */
 #define IXGBE_MDIO_AUTO_NEG_ADVT       0x10 /* AUTO_NEG Advt Reg */
 #define IXGBE_MDIO_AUTO_NEG_LP         0x13 /* AUTO_NEG LP Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT   0x3C /* AUTO_NEG EEE Advt Reg */
 
+#define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE       0x0800 /* Set low power mode */
+
 #define IXGBE_MDIO_TX_VENDOR_ALARMS_3  0xCC02 /* Vendor Alarms 3 Reg */
 #define IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK 0x3 /* PHY Reset Complete Mask */
 #define IXGBE_MDIO_GLOBAL_RES_PR_10 0xC479 /* Global Resv Provisioning 10 Reg */
 #define IXGBE_MDIO_POWER_UP_STALL      0x8000 /* Power Up Stall */
+#define IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK    0xFF00 /* int std mask */
+#define IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG    0xFC00 /* chip std int flag */
+#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK    0xFF01 /* int chip-wide mask */
+#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG    0xFC01 /* int chip-wide mask */
+#define IXGBE_MDIO_GLOBAL_ALARM_1              0xCC00 /* Global alarm 1 */
+#define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL    0x4000 /* high temp failure */
+#define IXGBE_MDIO_GLOBAL_INT_MASK             0xD400 /* Global int mask */
+/* autoneg vendor alarm int enable */
+#define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN    0x1000
+#define IXGBE_MDIO_GLOBAL_ALARM_1_INT          0x4 /* int in Global alarm 1 */
+#define IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN       0x1 /* vendor alarm int enable */
+#define IXGBE_MDIO_GLOBAL_STD_ALM2_INT         0x200 /* vendor alarm2 int mask */
+#define IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN       0x4000 /* int high temp enable */
 
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR        0xC30A /* PHY_XS SDA/SCL Addr Reg */
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA        0xC30B /* PHY_XS SDA/SCL Data Reg */
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT        0xC30C /* PHY_XS SDA/SCL Stat Reg */
+#define IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK    0xD401 /* PHY TX Vendor LASI */
+#define IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN      0x1 /* PHY TX Vendor LASI enable */
 #define IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR     0x9 /* Standard Tx Dis Reg */
 #define IXGBE_MDIO_PMD_GLOBAL_TX_DISABLE       0x0001 /* PMD Global Tx Dis */
 
@@ -1233,6 +1353,8 @@ struct ixgbe_thermal_sensor_data {
 #define TN1010_PHY_ID    0x00A19410
 #define TNX_FW_REV       0xB
 #define X540_PHY_ID      0x01540200
+#define X550_PHY_ID      0x01540220
+#define X557_PHY_ID      0x01540240
 #define QT2022_PHY_ID    0x0043A400
 #define ATH_PHY_ID       0x03429050
 #define AQ_FW_REV        0x20
@@ -1253,9 +1375,25 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_CONTROL_SOL_NL     0x0000
 
 /* General purpose Interrupt Enable */
-#define IXGBE_SDP0_GPIEN         0x00000001 /* SDP0 */
-#define IXGBE_SDP1_GPIEN         0x00000002 /* SDP1 */
-#define IXGBE_SDP2_GPIEN         0x00000004 /* SDP2 */
+#define IXGBE_SDP0_GPIEN_8259X         0x00000001 /* SDP0 */
+#define IXGBE_SDP1_GPIEN_8259X         0x00000002 /* SDP1 */
+#define IXGBE_SDP2_GPIEN_8259X         0x00000004 /* SDP2 */
+#define IXGBE_SDP0_GPIEN_X540          0x00000002 /* SDP0 on X540 and X550 */
+#define IXGBE_SDP1_GPIEN_X540          0x00000004 /* SDP1 on X540 and X550 */
+#define IXGBE_SDP2_GPIEN_X540          0x00000008 /* SDP2 on X540 and X550 */
+#define IXGBE_SDP0_GPIEN_X550          IXGBE_SDP0_GPIEN_X540
+#define IXGBE_SDP1_GPIEN_X550          IXGBE_SDP1_GPIEN_X540
+#define IXGBE_SDP2_GPIEN_X550          IXGBE_SDP2_GPIEN_X540
+#define IXGBE_SDP0_GPIEN_X550EM_x      IXGBE_SDP0_GPIEN_X540
+#define IXGBE_SDP1_GPIEN_X550EM_x      IXGBE_SDP1_GPIEN_X540
+#define IXGBE_SDP2_GPIEN_X550EM_x      IXGBE_SDP2_GPIEN_X540
+#define IXGBE_SDP0_GPIEN_X550EM_a      IXGBE_SDP0_GPIEN_X540
+#define IXGBE_SDP1_GPIEN_X550EM_a      IXGBE_SDP1_GPIEN_X540
+#define IXGBE_SDP2_GPIEN_X550EM_a      IXGBE_SDP2_GPIEN_X540
+#define IXGBE_SDP0_GPIEN(_hw)          IXGBE_BY_MAC((_hw), SDP0_GPIEN)
+#define IXGBE_SDP1_GPIEN(_hw)          IXGBE_BY_MAC((_hw), SDP1_GPIEN)
+#define IXGBE_SDP2_GPIEN(_hw)          IXGBE_BY_MAC((_hw), SDP2_GPIEN)
+
 #define IXGBE_GPIE_MSIX_MODE     0x00000010 /* MSI-X mode */
 #define IXGBE_GPIE_OCD           0x00000020 /* Other Clear Disable */
 #define IXGBE_GPIE_EIMEN         0x00000040 /* Immediate Interrupt Enable */
@@ -1417,9 +1555,25 @@ enum {
 #define IXGBE_EICR_MNG          0x00400000 /* Manageability Event Interrupt */
 #define IXGBE_EICR_TS           0x00800000 /* Thermal Sensor Event */
 #define IXGBE_EICR_TIMESYNC     0x01000000 /* Timesync Event */
-#define IXGBE_EICR_GPI_SDP0     0x01000000 /* Gen Purpose Interrupt on SDP0 */
-#define IXGBE_EICR_GPI_SDP1     0x02000000 /* Gen Purpose Interrupt on SDP1 */
-#define IXGBE_EICR_GPI_SDP2     0x04000000 /* Gen Purpose Interrupt on SDP2 */
+#define IXGBE_EICR_GPI_SDP0_8259X      0x01000000 /* Gen Purpose INT on SDP0 */
+#define IXGBE_EICR_GPI_SDP1_8259X      0x02000000 /* Gen Purpose INT on SDP1 */
+#define IXGBE_EICR_GPI_SDP2_8259X      0x04000000 /* Gen Purpose INT on SDP2 */
+#define IXGBE_EICR_GPI_SDP0_X540       0x02000000
+#define IXGBE_EICR_GPI_SDP1_X540       0x04000000
+#define IXGBE_EICR_GPI_SDP2_X540       0x08000000
+#define IXGBE_EICR_GPI_SDP0_X550       IXGBE_EICR_GPI_SDP0_X540
+#define IXGBE_EICR_GPI_SDP1_X550       IXGBE_EICR_GPI_SDP1_X540
+#define IXGBE_EICR_GPI_SDP2_X550       IXGBE_EICR_GPI_SDP2_X540
+#define IXGBE_EICR_GPI_SDP0_X550EM_x   IXGBE_EICR_GPI_SDP0_X540
+#define IXGBE_EICR_GPI_SDP1_X550EM_x   IXGBE_EICR_GPI_SDP1_X540
+#define IXGBE_EICR_GPI_SDP2_X550EM_x   IXGBE_EICR_GPI_SDP2_X540
+#define IXGBE_EICR_GPI_SDP0_X550EM_a   IXGBE_EICR_GPI_SDP0_X540
+#define IXGBE_EICR_GPI_SDP1_X550EM_a   IXGBE_EICR_GPI_SDP1_X540
+#define IXGBE_EICR_GPI_SDP2_X550EM_a   IXGBE_EICR_GPI_SDP2_X540
+#define IXGBE_EICR_GPI_SDP0(_hw)       IXGBE_BY_MAC((_hw), EICR_GPI_SDP0)
+#define IXGBE_EICR_GPI_SDP1(_hw)       IXGBE_BY_MAC((_hw), EICR_GPI_SDP1)
+#define IXGBE_EICR_GPI_SDP2(_hw)       IXGBE_BY_MAC((_hw), EICR_GPI_SDP2)
+
 #define IXGBE_EICR_ECC          0x10000000 /* ECC Error */
 #define IXGBE_EICR_PBUR         0x10000000 /* Packet Buffer Handler Error */
 #define IXGBE_EICR_DHER         0x20000000 /* Descriptor Handler Error */
@@ -1435,9 +1589,9 @@ enum {
 #define IXGBE_EICS_LSC          IXGBE_EICR_LSC       /* Link Status Change */
 #define IXGBE_EICS_MNG          IXGBE_EICR_MNG       /* MNG Event Interrupt */
 #define IXGBE_EICS_TIMESYNC     IXGBE_EICR_TIMESYNC  /* Timesync Event */
-#define IXGBE_EICS_GPI_SDP0     IXGBE_EICR_GPI_SDP0  /* SDP0 Gen Purpose Int */
-#define IXGBE_EICS_GPI_SDP1     IXGBE_EICR_GPI_SDP1  /* SDP1 Gen Purpose Int */
-#define IXGBE_EICS_GPI_SDP2     IXGBE_EICR_GPI_SDP2  /* SDP2 Gen Purpose Int */
+#define IXGBE_EICS_GPI_SDP0(_hw)       IXGBE_EICR_GPI_SDP0(_hw)
+#define IXGBE_EICS_GPI_SDP1(_hw)       IXGBE_EICR_GPI_SDP1(_hw)
+#define IXGBE_EICS_GPI_SDP2(_hw)       IXGBE_EICR_GPI_SDP2(_hw)
 #define IXGBE_EICS_ECC          IXGBE_EICR_ECC       /* ECC Error */
 #define IXGBE_EICS_PBUR         IXGBE_EICR_PBUR      /* Pkt Buf Handler Err */
 #define IXGBE_EICS_DHER         IXGBE_EICR_DHER      /* Desc Handler Error */
@@ -1454,9 +1608,9 @@ enum {
 #define IXGBE_EIMS_MNG          IXGBE_EICR_MNG       /* MNG Event Interrupt */
 #define IXGBE_EIMS_TS           IXGBE_EICR_TS        /* Thermel Sensor Event */
 #define IXGBE_EIMS_TIMESYNC     IXGBE_EICR_TIMESYNC  /* Timesync Event */
-#define IXGBE_EIMS_GPI_SDP0     IXGBE_EICR_GPI_SDP0  /* SDP0 Gen Purpose Int */
-#define IXGBE_EIMS_GPI_SDP1     IXGBE_EICR_GPI_SDP1  /* SDP1 Gen Purpose Int */
-#define IXGBE_EIMS_GPI_SDP2     IXGBE_EICR_GPI_SDP2  /* SDP2 Gen Purpose Int */
+#define IXGBE_EIMS_GPI_SDP0(_hw)       IXGBE_EICR_GPI_SDP0(_hw)
+#define IXGBE_EIMS_GPI_SDP1(_hw)       IXGBE_EICR_GPI_SDP1(_hw)
+#define IXGBE_EIMS_GPI_SDP2(_hw)       IXGBE_EICR_GPI_SDP2(_hw)
 #define IXGBE_EIMS_ECC          IXGBE_EICR_ECC       /* ECC Error */
 #define IXGBE_EIMS_PBUR         IXGBE_EICR_PBUR      /* Pkt Buf Handler Err */
 #define IXGBE_EIMS_DHER         IXGBE_EICR_DHER      /* Descr Handler Error */
@@ -1472,9 +1626,9 @@ enum {
 #define IXGBE_EIMC_LSC          IXGBE_EICR_LSC       /* Link Status Change */
 #define IXGBE_EIMC_MNG          IXGBE_EICR_MNG       /* MNG Event Interrupt */
 #define IXGBE_EIMC_TIMESYNC     IXGBE_EICR_TIMESYNC  /* Timesync Event */
-#define IXGBE_EIMC_GPI_SDP0     IXGBE_EICR_GPI_SDP0  /* SDP0 Gen Purpose Int */
-#define IXGBE_EIMC_GPI_SDP1     IXGBE_EICR_GPI_SDP1  /* SDP1 Gen Purpose Int */
-#define IXGBE_EIMC_GPI_SDP2     IXGBE_EICR_GPI_SDP2  /* SDP2 Gen Purpose Int */
+#define IXGBE_EIMC_GPI_SDP0(_hw)       IXGBE_EICR_GPI_SDP0(_hw)
+#define IXGBE_EIMC_GPI_SDP1(_hw)       IXGBE_EICR_GPI_SDP1(_hw)
+#define IXGBE_EIMC_GPI_SDP2(_hw)       IXGBE_EICR_GPI_SDP2(_hw)
 #define IXGBE_EIMC_ECC          IXGBE_EICR_ECC       /* ECC Error */
 #define IXGBE_EIMC_PBUR         IXGBE_EICR_PBUR      /* Pkt Buf Handler Err */
 #define IXGBE_EIMC_DHER         IXGBE_EICR_DHER      /* Desc Handler Err */
@@ -2741,6 +2895,37 @@ union ixgbe_atr_hash_dword {
        __be32 dword;
 };
 
+#define IXGBE_MVALS_INIT(m)            \
+       IXGBE_CAT(EEC, m),              \
+       IXGBE_CAT(FLA, m),              \
+       IXGBE_CAT(GRC, m),              \
+       IXGBE_CAT(SRAMREL, m),          \
+       IXGBE_CAT(FACTPS, m),           \
+       IXGBE_CAT(SWSM, m),             \
+       IXGBE_CAT(SWFW_SYNC, m),        \
+       IXGBE_CAT(FWSM, m),             \
+       IXGBE_CAT(SDP0_GPIEN, m),       \
+       IXGBE_CAT(SDP1_GPIEN, m),       \
+       IXGBE_CAT(SDP2_GPIEN, m),       \
+       IXGBE_CAT(EICR_GPI_SDP0, m),    \
+       IXGBE_CAT(EICR_GPI_SDP1, m),    \
+       IXGBE_CAT(EICR_GPI_SDP2, m),    \
+       IXGBE_CAT(CIAA, m),             \
+       IXGBE_CAT(CIAD, m),             \
+       IXGBE_CAT(I2C_CLK_IN, m),       \
+       IXGBE_CAT(I2C_CLK_OUT, m),      \
+       IXGBE_CAT(I2C_DATA_IN, m),      \
+       IXGBE_CAT(I2C_DATA_OUT, m),     \
+       IXGBE_CAT(I2C_DATA_OE_N_EN, m), \
+       IXGBE_CAT(I2C_BB_EN, m),        \
+       IXGBE_CAT(I2C_CLK_OE_N_EN, m),  \
+       IXGBE_CAT(I2CCTL, m)
+
+enum ixgbe_mvals {
+       IXGBE_MVALS_INIT(IDX),
+       IXGBE_MVALS_IDX_LIMIT
+};
+
 enum ixgbe_eeprom_type {
        ixgbe_eeprom_uninitialized = 0,
        ixgbe_eeprom_spi,
@@ -3112,6 +3297,8 @@ struct ixgbe_phy_operations {
        s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
        s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
        s32 (*check_overtemp)(struct ixgbe_hw *);
+       s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
+       s32 (*handle_lasi)(struct ixgbe_hw *hw);
 };
 
 struct ixgbe_eeprom_info {
@@ -3173,6 +3360,7 @@ struct ixgbe_phy_info {
        bool                            multispeed_fiber;
        bool                            reset_if_overtemp;
        bool                            qsfp_shared_i2c_bus;
+       u32                             nw_mng_if_sel;
 };
 
 #include "ixgbe_mbx.h"
@@ -3216,6 +3404,7 @@ struct ixgbe_hw {
        struct ixgbe_eeprom_info        eeprom;
        struct ixgbe_bus_info           bus;
        struct ixgbe_mbx_info           mbx;
+       const u32                       *mvals;
        u16                             device_id;
        u16                             vendor_id;
        u16                             subsystem_device_id;
@@ -3234,6 +3423,7 @@ struct ixgbe_info {
        struct ixgbe_eeprom_operations  *eeprom_ops;
        struct ixgbe_phy_operations     *phy_ops;
        struct ixgbe_mbx_operations     *mbx_ops;
+       const u32                       *mvals;
 };
 
 
@@ -3339,4 +3529,6 @@ struct ixgbe_info {
 #define IXGBE_SB_IOSF_TARGET_KX4_PCS0  2
 #define IXGBE_SB_IOSF_TARGET_KX4_PCS1  3
 
+#define IXGBE_NW_MNG_IF_SEL            0x00011178
+#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE       BIT(24)
 #endif /* _IXGBE_TYPE_H_ */
index 0a8b5e42e1a9b2dbd66e776962cacbb47ec021d2..032a5870abd11bab111e2e317d821fbf454572c2 100644 (file)
@@ -202,7 +202,7 @@ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
                eeprom->semaphore_delay = 10;
                eeprom->type = ixgbe_flash;
 
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
                eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
                                    IXGBE_EEC_SIZE_SHIFT);
                eeprom->word_size = 1 << (eeprom_size +
@@ -504,8 +504,8 @@ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
                return status;
        }
 
-       flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+       flup = IXGBE_READ_REG(hw, IXGBE_EEC(hw)) | IXGBE_EEC_FLUP;
+       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), flup);
 
        status = ixgbe_poll_flash_update_done_X540(hw);
        if (status == 0)
@@ -514,11 +514,11 @@ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
                hw_dbg(hw, "Flash update time out\n");
 
        if (hw->revision_id == 0) {
-               flup = IXGBE_READ_REG(hw, IXGBE_EEC);
+               flup = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
                if (flup & IXGBE_EEC_SEC1VAL) {
                        flup |= IXGBE_EEC_FLUP;
-                       IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+                       IXGBE_WRITE_REG(hw, IXGBE_EEC(hw), flup);
                }
 
                status = ixgbe_poll_flash_update_done_X540(hw);
@@ -544,7 +544,7 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
        u32 reg;
 
        for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
-               reg = IXGBE_READ_REG(hw, IXGBE_EEC);
+               reg = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
                if (reg & IXGBE_EEC_FLUDONE)
                        return 0;
                udelay(5);
@@ -580,10 +580,10 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
                if (ixgbe_get_swfw_sync_semaphore(hw))
                        return IXGBE_ERR_SWFW_SYNC;
 
-               swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+               swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
                if (!(swfw_sync & (fwmask | swmask | hwmask))) {
                        swfw_sync |= swmask;
-                       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+                       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
                        ixgbe_release_swfw_sync_semaphore(hw);
                        break;
                } else {
@@ -605,13 +605,13 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
         * corresponding FW/HW bits in the SW_FW_SYNC register.
         */
        if (i >= timeout) {
-               swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+               swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
                if (swfw_sync & (fwmask | hwmask)) {
                        if (ixgbe_get_swfw_sync_semaphore(hw))
                                return IXGBE_ERR_SWFW_SYNC;
 
                        swfw_sync |= swmask;
-                       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+                       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
                        ixgbe_release_swfw_sync_semaphore(hw);
                }
        }
@@ -635,9 +635,9 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
 
        ixgbe_get_swfw_sync_semaphore(hw);
 
-       swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+       swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
        swfw_sync &= ~swmask;
-       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync);
 
        ixgbe_release_swfw_sync_semaphore(hw);
        usleep_range(5000, 10000);
@@ -660,7 +660,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
                /* If the SMBI bit is 0 when we read it, then the bit will be
                 * set and we have the semaphore
                 */
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
                if (!(swsm & IXGBE_SWSM_SMBI))
                        break;
                usleep_range(50, 100);
@@ -674,7 +674,7 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
 
        /* Now get the semaphore between SW/FW through the REGSMP bit */
        for (i = 0; i < timeout; i++) {
-               swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
                if (!(swsm & IXGBE_SWFW_REGSMP))
                        return 0;
 
@@ -696,13 +696,13 @@ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
 
        /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
 
-       swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+       swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
        swsm &= ~IXGBE_SWFW_REGSMP;
-       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
+       IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swsm);
 
-       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
        swsm &= ~IXGBE_SWSM_SMBI;
-       IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+       IXGBE_WRITE_REG(hw, IXGBE_SWSM(hw), swsm);
 
        IXGBE_WRITE_FLUSH(hw);
 }
@@ -850,9 +850,14 @@ static struct ixgbe_phy_operations phy_ops_X540 = {
        .read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_generic,
        .write_i2c_eeprom       = &ixgbe_write_i2c_eeprom_generic,
        .check_overtemp         = &ixgbe_tn_check_overtemp,
+       .set_phy_power          = &ixgbe_set_copper_phy_power,
        .get_firmware_version   = &ixgbe_get_phy_firmware_version_generic,
 };
 
+static const u32 ixgbe_mvals_X540[IXGBE_MVALS_IDX_LIMIT] = {
+       IXGBE_MVALS_INIT(X540)
+};
+
 struct ixgbe_info ixgbe_X540_info = {
        .mac                    = ixgbe_mac_X540,
        .get_invariants         = &ixgbe_get_invariants_X540,
@@ -860,4 +865,5 @@ struct ixgbe_info ixgbe_X540_info = {
        .eeprom_ops             = &eeprom_ops_X540,
        .phy_ops                = &phy_ops_X540,
        .mbx_ops                = &mbx_ops_generic,
+       .mvals                  = ixgbe_mvals_X540,
 };
index b0236985e9156e3c66dee931e3a20adc3989bc55..7581da13e92a3cecbb6782cf040d3d9f03290468 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  *  Intel 10 Gigabit PCI Express Linux driver
- *  Copyright(c) 1999 - 2014 Intel Corporation.
+ *  Copyright(c) 1999 - 2015 Intel Corporation.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 
+/** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control
+ *  @hw: pointer to hardware structure
+ **/
+static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
+{
+       u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+       if (hw->bus.lan_id) {
+               esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
+               esdp |= IXGBE_ESDP_SDP1_DIR;
+       }
+       esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+}
+
 /** ixgbe_identify_phy_x550em - Get PHY type based on device id
  *  @hw: pointer to hardware structure
  *
  */
 static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
 {
-       u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
-
        switch (hw->device_id) {
        case IXGBE_DEV_ID_X550EM_X_SFP:
                /* set up for CS4227 usage */
                hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
-               if (hw->bus.lan_id) {
-                       esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
-                       esdp |= IXGBE_ESDP_SDP1_DIR;
-               }
-               esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
-               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               ixgbe_setup_mux_ctl(hw);
 
                return ixgbe_identify_module_generic(hw);
        case IXGBE_DEV_ID_X550EM_X_KX4:
@@ -90,7 +99,7 @@ static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
                eeprom->semaphore_delay = 10;
                eeprom->type = ixgbe_flash;
 
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
                eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
                                    IXGBE_EEC_SIZE_SHIFT);
                eeprom->word_size = 1 << (eeprom_size +
@@ -704,111 +713,6 @@ static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
        return status;
 }
 
-/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
- *  @hw: pointer to hardware structure
- **/
-static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
-{
-       struct ixgbe_mac_info *mac = &hw->mac;
-
-       /* CS4227 does not support autoneg, so disable the laser control
-        * functions for SFP+ fiber
-        */
-       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) {
-               mac->ops.disable_tx_laser = NULL;
-               mac->ops.enable_tx_laser = NULL;
-               mac->ops.flap_tx_laser = NULL;
-       }
-}
-
-/** ixgbe_setup_sfp_modules_X550em - Setup SFP module
- * @hw: pointer to hardware structure
- */
-static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
-{
-       bool setup_linear;
-       u16 reg_slice, edc_mode;
-       s32 ret_val;
-
-       switch (hw->phy.sfp_type) {
-       case ixgbe_sfp_type_unknown:
-               return 0;
-       case ixgbe_sfp_type_not_present:
-               return IXGBE_ERR_SFP_NOT_PRESENT;
-       case ixgbe_sfp_type_da_cu_core0:
-       case ixgbe_sfp_type_da_cu_core1:
-               setup_linear = true;
-               break;
-       case ixgbe_sfp_type_srlr_core0:
-       case ixgbe_sfp_type_srlr_core1:
-       case ixgbe_sfp_type_da_act_lmt_core0:
-       case ixgbe_sfp_type_da_act_lmt_core1:
-       case ixgbe_sfp_type_1g_sx_core0:
-       case ixgbe_sfp_type_1g_sx_core1:
-               setup_linear = false;
-               break;
-       default:
-               return IXGBE_ERR_SFP_NOT_SUPPORTED;
-       }
-
-       ixgbe_init_mac_link_ops_X550em(hw);
-       hw->phy.ops.reset = NULL;
-
-       /* The CS4227 slice address is the base address + the port-pair reg
-        * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
-        */
-       reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
-
-       if (setup_linear)
-               edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-       else
-               edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-
-       /* Configure CS4227 for connection type. */
-       ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-                                                edc_mode);
-
-       if (ret_val)
-               ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice,
-                                                        edc_mode);
-
-       return ret_val;
-}
-
-/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
- * @hw: pointer to hardware structure
- * @speed: pointer to link speed
- * @autoneg: true when autoneg or autotry is enabled
- **/
-static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
-                                             ixgbe_link_speed *speed,
-                                             bool *autoneg)
-{
-       /* SFP */
-       if (hw->phy.media_type == ixgbe_media_type_fiber) {
-               /* CS4227 SFP must not enable auto-negotiation */
-               *autoneg = false;
-
-               if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-                   hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
-                       *speed = IXGBE_LINK_SPEED_1GB_FULL;
-                       return 0;
-               }
-
-               /* Link capabilities are based on SFP */
-               if (hw->phy.multispeed_fiber)
-                       *speed = IXGBE_LINK_SPEED_10GB_FULL |
-                                IXGBE_LINK_SPEED_1GB_FULL;
-               else
-                       *speed = IXGBE_LINK_SPEED_10GB_FULL;
-       } else {
-               *speed = IXGBE_LINK_SPEED_10GB_FULL |
-                        IXGBE_LINK_SPEED_1GB_FULL;
-               *autoneg = true;
-       }
-       return 0;
-}
-
 /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the
  *  IOSF device
  *
@@ -891,7 +795,7 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
        }
 
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
+                               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status)
                return status;
@@ -973,6 +877,417 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
        return status;
 }
 
+/**
+ * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait_to_complete: true when waiting for completion is needed
+ *
+ * Setup internal/external PHY link speed based on link speed, then set
+ * external PHY auto advertised link speed.
+ *
+ * Returns error status for any failure
+ **/
+static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw,
+                                        ixgbe_link_speed speed,
+                                        bool autoneg_wait)
+{
+       s32 status;
+       ixgbe_link_speed force_speed;
+
+       /* Setup internal/external PHY link speed to iXFI (10G), unless
+        * only 1G is auto advertised then setup KX link.
+        */
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+               force_speed = IXGBE_LINK_SPEED_10GB_FULL;
+       else
+               force_speed = IXGBE_LINK_SPEED_1GB_FULL;
+
+       /* If internal link mode is XFI, then setup XFI internal link. */
+       if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+               status = ixgbe_setup_ixfi_x550em(hw, &force_speed);
+
+               if (status)
+                       return status;
+       }
+
+       return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
+}
+
+/** ixgbe_check_link_t_X550em - Determine link and speed status
+  * @hw: pointer to hardware structure
+  * @speed: pointer to link speed
+  * @link_up: true when link is up
+  * @link_up_wait_to_complete: bool used to wait for link up or not
+  *
+  * Check that both the MAC and X557 external PHY have link.
+  **/
+static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw,
+                                    ixgbe_link_speed *speed,
+                                    bool *link_up,
+                                    bool link_up_wait_to_complete)
+{
+       u32 status;
+       u16 autoneg_status;
+
+       if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
+               return IXGBE_ERR_CONFIG;
+
+       status = ixgbe_check_mac_link_generic(hw, speed, link_up,
+                                             link_up_wait_to_complete);
+
+       /* If check link fails or MAC link is not up, then return */
+       if (status || !(*link_up))
+               return status;
+
+        /* MAC link is up, so check external PHY link.
+         * Read this twice back to back to indicate current status.
+         */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &autoneg_status);
+       if (status)
+               return status;
+
+       /* If external PHY link is not up, then indicate link not up */
+       if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
+               *link_up = false;
+
+       return 0;
+}
+
+/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
+ *  @hw: pointer to hardware structure
+ **/
+static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
+{
+       struct ixgbe_mac_info *mac = &hw->mac;
+
+       switch (mac->ops.get_media_type(hw)) {
+       case ixgbe_media_type_fiber:
+               /* CS4227 does not support autoneg, so disable the laser control
+                * functions for SFP+ fiber
+                */
+               mac->ops.disable_tx_laser = NULL;
+               mac->ops.enable_tx_laser = NULL;
+               mac->ops.flap_tx_laser = NULL;
+               break;
+       case ixgbe_media_type_copper:
+               mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
+               mac->ops.check_link = ixgbe_check_link_t_X550em;
+               break;
+       default:
+               break;
+       }
+}
+
+/** ixgbe_setup_sfp_modules_X550em - Setup SFP module
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
+{
+       bool setup_linear;
+       u16 reg_slice, edc_mode;
+       s32 ret_val;
+
+       switch (hw->phy.sfp_type) {
+       case ixgbe_sfp_type_unknown:
+               return 0;
+       case ixgbe_sfp_type_not_present:
+               return IXGBE_ERR_SFP_NOT_PRESENT;
+       case ixgbe_sfp_type_da_cu_core0:
+       case ixgbe_sfp_type_da_cu_core1:
+               setup_linear = true;
+               break;
+       case ixgbe_sfp_type_srlr_core0:
+       case ixgbe_sfp_type_srlr_core1:
+       case ixgbe_sfp_type_da_act_lmt_core0:
+       case ixgbe_sfp_type_da_act_lmt_core1:
+       case ixgbe_sfp_type_1g_sx_core0:
+       case ixgbe_sfp_type_1g_sx_core1:
+               setup_linear = false;
+               break;
+       default:
+               return IXGBE_ERR_SFP_NOT_SUPPORTED;
+       }
+
+       ixgbe_init_mac_link_ops_X550em(hw);
+       hw->phy.ops.reset = NULL;
+
+       /* The CS4227 slice address is the base address + the port-pair reg
+        * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
+        */
+       reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
+
+       if (setup_linear)
+               edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+       else
+               edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+
+       /* Configure CS4227 for connection type. */
+       ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                                edc_mode);
+
+       if (ret_val)
+               ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice,
+                                                        edc_mode);
+
+       return ret_val;
+}
+
+/** ixgbe_get_link_capabilities_x550em - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: true when autoneg or autotry is enabled
+ **/
+static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
+                                             ixgbe_link_speed *speed,
+                                             bool *autoneg)
+{
+       /* SFP */
+       if (hw->phy.media_type == ixgbe_media_type_fiber) {
+               /* CS4227 SFP must not enable auto-negotiation */
+               *autoneg = false;
+
+               if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+                   hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
+                       *speed = IXGBE_LINK_SPEED_1GB_FULL;
+                       return 0;
+               }
+
+               /* Link capabilities are based on SFP */
+               if (hw->phy.multispeed_fiber)
+                       *speed = IXGBE_LINK_SPEED_10GB_FULL |
+                                IXGBE_LINK_SPEED_1GB_FULL;
+               else
+                       *speed = IXGBE_LINK_SPEED_10GB_FULL;
+       } else {
+               *speed = IXGBE_LINK_SPEED_10GB_FULL |
+                        IXGBE_LINK_SPEED_1GB_FULL;
+               *autoneg = true;
+       }
+       return 0;
+}
+
+/**
+ * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause
+ * @hw: pointer to hardware structure
+ * @lsc: pointer to boolean flag which indicates whether external Base T
+ *      PHY interrupt is lsc
+ *
+ * Determime if external Base T PHY interrupt cause is high temperature
+ * failure alarm or link status change.
+ *
+ * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
+ * failure alarm, else return PHY access status.
+ **/
+static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
+{
+       u32 status;
+       u16 reg;
+
+       *lsc = false;
+
+       /* Vendor alarm triggered */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+
+       if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
+               return status;
+
+       /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+
+       if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
+                               IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
+               return status;
+
+       /* High temperature failure alarm triggered */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+
+       if (status)
+               return status;
+
+       /* If high temperature failure, then return over temp error and exit */
+       if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
+               /* power down the PHY in case the PHY FW didn't already */
+               ixgbe_set_copper_phy_power(hw, false);
+               return IXGBE_ERR_OVERTEMP;
+       }
+
+       /* Vendor alarm 2 triggered */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+
+       if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
+               return status;
+
+       /* link connect/disconnect event occurred */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+
+       if (status)
+               return status;
+
+       /* Indicate LSC */
+       if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC)
+               *lsc = true;
+
+       return 0;
+}
+
+/**
+ * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts
+ * @hw: pointer to hardware structure
+ *
+ * Enable link status change and temperature failure alarm for the external
+ * Base T PHY
+ *
+ * Returns PHY access status
+ **/
+static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
+{
+       u32 status;
+       u16 reg;
+       bool lsc;
+
+       /* Clear interrupt flags */
+       status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
+
+       /* Enable link status change alarm */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+       if (status)
+               return status;
+
+       reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
+
+       status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
+                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
+       if (status)
+               return status;
+
+       /* Enables high temperature failure alarm */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+       if (status)
+               return status;
+
+       reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN;
+
+       status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+       if (status)
+               return status;
+
+       /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+       if (status)
+               return status;
+
+       reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
+               IXGBE_MDIO_GLOBAL_ALARM_1_INT);
+
+       status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+       if (status)
+               return status;
+
+       /* Enable chip-wide vendor alarm */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+       if (status)
+               return status;
+
+       reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
+
+       status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+
+       return status;
+}
+
+/**
+ * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
+ * @hw: pointer to hardware structure
+ *
+ * Handle external Base T PHY interrupt. If high temperature
+ * failure alarm then return error, else if link status change
+ * then setup internal/external PHY link
+ *
+ * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
+ * failure alarm, else return PHY access status.
+ **/
+static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
+{
+       struct ixgbe_phy_info *phy = &hw->phy;
+       bool lsc;
+       u32 status;
+
+       status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
+       if (status)
+               return status;
+
+       if (lsc)
+               return phy->ops.setup_internal_link(hw);
+
+       return 0;
+}
+
+/**
+ * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed.
+ * @hw: pointer to hardware structure
+ * @speed: link speed
+ *
+ * Configures the integrated KR PHY.
+ **/
+static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw,
+                                      ixgbe_link_speed speed)
+{
+       s32 status;
+       u32 reg_val;
+
+       status = ixgbe_read_iosf_sb_reg_x550(hw,
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       if (status)
+               return status;
+
+       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+       reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
+                    IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
+       reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
+                    IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
+
+       /* Advertise 10G support. */
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
+
+       /* Advertise 1G support. */
+       if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
+
+       /* Restart auto-negotiation. */
+       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+       status = ixgbe_write_iosf_sb_reg_x550(hw,
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       return status;
+}
+
 /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
  *  @hw: pointer to hardware structure
  *
@@ -1018,85 +1333,82 @@ static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw)
  **/
 static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
 {
-       s32 status;
-       u32 reg_val;
+       return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised);
+}
 
-       status = ixgbe_read_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-                                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
-       if (status)
-               return status;
+/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
+ *  @hw: address of hardware structure
+ *  @link_up: address of boolean to indicate link status
+ *
+ *  Returns error code if unable to get link status.
+ **/
+static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
+{
+       u32 ret;
+       u16 autoneg_status;
 
-       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
-       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ;
-       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC;
-       reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
-                    IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
+       *link_up = false;
 
-       /* Advertise 10G support. */
-       if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR;
+       /* read this twice back to back to indicate current status */
+       ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                  IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                  &autoneg_status);
+       if (ret)
+               return ret;
 
-       /* Advertise 1G support. */
-       if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
-               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
+       ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                  IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                  &autoneg_status);
+       if (ret)
+               return ret;
 
-       /* Restart auto-negotiation. */
-       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
-       status = ixgbe_write_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-                                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+       *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
 
-       return status;
+       return 0;
 }
 
-/** ixgbe_setup_internal_phy_x550em - Configure integrated KR PHY
+/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link
  *  @hw: point to hardware structure
  *
- *  Configures the integrated KR PHY to talk to the external PHY. The base
- *  driver will call this function when it gets notification via interrupt from
- *  the external PHY. This function forces the internal PHY into iXFI mode at
- *  the correct speed.
+ *  Configures the link between the integrated KR PHY and the external X557 PHY
+ *  The driver will call this function when it gets a link status change
+ *  interrupt from the X557 PHY. This function configures the link speed
+ *  between the PHYs to match the link speed of the BASE-T link.
  *
- *  A return of a non-zero value indicates an error, and the base driver should
- *  not report link up.
+ * A return of a non-zero value indicates an error, and the base driver should
+ * not report link up.
  **/
-static s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw)
+static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
 {
-       s32 status;
-       u16 lasi, autoneg_status, speed;
        ixgbe_link_speed force_speed;
+       bool link_up;
+       u32 status;
+       u16 speed;
 
-       /* Verify that the external link status has changed */
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_XENPAK_LASI_STATUS,
-                                     IXGBE_MDIO_PMA_PMD_DEV_TYPE, &lasi);
+       if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
+               return IXGBE_ERR_CONFIG;
+
+       /* If link is not up, then there is no setup necessary so return  */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
        if (status)
                return status;
 
-       /* If there was no change in link status, we can just exit */
-       if (!(lasi & IXGBE_XENPAK_LASI_LINK_STATUS_ALARM))
+       if (!link_up)
                return 0;
 
-       /* we read this twice back to back to indicate current status */
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
+                                     &speed);
        if (status)
                return status;
 
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
+       /* If link is not still up, then no setup is necessary so return */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
        if (status)
                return status;
 
-       /* If link is not up return an error indicating treat link as down */
-       if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
-               return IXGBE_ERR_INVALID_LINK_SETTINGS;
-
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
-                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &speed);
+       if (!link_up)
+               return 0;
 
        /* clear everything but the speed and duplex bits */
        speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
@@ -1116,6 +1428,22 @@ static s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw)
        return ixgbe_setup_ixfi_x550em(hw, &force_speed);
 }
 
+/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI
+ *  @hw: pointer to hardware structure
+ **/
+static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw)
+{
+       s32 status;
+
+       status = ixgbe_reset_phy_generic(hw);
+
+       if (status)
+               return status;
+
+       /* Configure Link Status Alarm and Temperature Threshold interrupts */
+       return ixgbe_enable_lasi_ext_t_x550em(hw);
+}
+
 /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init
  *  @hw: pointer to hardware structure
  *
@@ -1126,25 +1454,32 @@ static s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw)
 static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
 {
        struct ixgbe_phy_info *phy = &hw->phy;
+       ixgbe_link_speed speed;
        s32 ret_val;
-       u32 esdp;
 
-       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) {
-               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
-               phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
+       hw->mac.ops.set_lan_id(hw);
 
-               if (hw->bus.lan_id) {
-                       esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
-                       esdp |= IXGBE_ESDP_SDP1_DIR;
+       if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) {
+               phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
+               ixgbe_setup_mux_ctl(hw);
+
+               /* Save NW management interface connected on board. This is used
+                * to determine internal PHY mode.
+                */
+               phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
+
+               /* If internal PHY mode is KR, then initialize KR link */
+               if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
+                       speed = IXGBE_LINK_SPEED_10GB_FULL |
+                               IXGBE_LINK_SPEED_1GB_FULL;
+                       ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
                }
-               esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR);
-               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
        }
 
        /* Identify the PHY or SFP module */
        ret_val = phy->ops.identify(hw);
 
-       /* Setup function pointers based on detected SFP module and speeds */
+       /* Setup function pointers based on detected hardware */
        ixgbe_init_mac_link_ops_X550em(hw);
        if (phy->sfp_type != ixgbe_sfp_type_unknown)
                phy->ops.reset = NULL;
@@ -1162,11 +1497,30 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
                phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
                break;
        case ixgbe_phy_x550em_ext_t:
-               phy->ops.setup_internal_link = ixgbe_setup_internal_phy_x550em;
+               /* Save NW management interface connected on board. This is used
+                * to determine internal PHY mode
+                */
+               phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
+
+               /* If internal link mode is XFI, then setup iXFI internal link,
+                * else setup KR now.
+                */
+               if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+                       phy->ops.setup_internal_link =
+                                       ixgbe_setup_internal_phy_t_x550em;
+               } else {
+                       speed = IXGBE_LINK_SPEED_10GB_FULL |
+                               IXGBE_LINK_SPEED_1GB_FULL;
+                       ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
+               }
+
+               phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
+               phy->ops.reset = ixgbe_reset_phy_t_X550em;
                break;
        default:
                break;
        }
+
        return ret_val;
 }
 
@@ -1207,65 +1561,35 @@ static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
 {
        s32 status;
        u16 reg;
-       u32 retries = 2;
-
-       do {
-               /* decrement retries counter and exit if we hit 0 */
-               if (retries < 1) {
-                       hw_dbg(hw, "External PHY not yet finished resetting.");
-                       return IXGBE_ERR_PHY;
-               }
-               retries--;
-
-               status = hw->phy.ops.read_reg(hw,
-                                             IXGBE_MDIO_TX_VENDOR_ALARMS_3,
-                                             IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-                                             &reg);
-               if (status)
-                       return status;
-
-               /* Verify PHY FW reset has completed */
-       } while ((reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) != 1);
-
-       /* Set port to low power mode */
-       status = hw->phy.ops.read_reg(hw,
-                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
-                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
-                                     &reg);
-       if (status)
-               return status;
 
-       /* Enable the transmitter */
        status = hw->phy.ops.read_reg(hw,
-                                     IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR,
+                                     IXGBE_MDIO_TX_VENDOR_ALARMS_3,
                                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
                                      &reg);
        if (status)
                return status;
 
-       reg &= ~IXGBE_MDIO_PMD_GLOBAL_TX_DISABLE;
+       /* If PHY FW reset completed bit is set then this is the first
+        * SW instance after a power on so the PHY FW must be un-stalled.
+        */
+       if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
+               status = hw->phy.ops.read_reg(hw,
+                                       IXGBE_MDIO_GLOBAL_RES_PR_10,
+                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                       &reg);
+               if (status)
+                       return status;
 
-       status = hw->phy.ops.write_reg(hw,
-                                      IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR,
-                                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-                                      reg);
-       if (status)
-               return status;
+               reg &= ~IXGBE_MDIO_POWER_UP_STALL;
 
-       /* Un-stall the PHY FW */
-       status = hw->phy.ops.read_reg(hw,
-                                     IXGBE_MDIO_GLOBAL_RES_PR_10,
-                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
-                                     &reg);
-       if (status)
-               return status;
-
-       reg &= ~IXGBE_MDIO_POWER_UP_STALL;
+               status = hw->phy.ops.write_reg(hw,
+                                       IXGBE_MDIO_GLOBAL_RES_PR_10,
+                                       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                       reg);
+               if (status)
+                       return status;
+       }
 
-       status = hw->phy.ops.write_reg(hw,
-                                      IXGBE_MDIO_GLOBAL_RES_PR_10,
-                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
-                                      reg);
        return status;
 }
 
@@ -1282,6 +1606,7 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
        s32 status;
        u32 ctrl = 0;
        u32 i;
+       u32 hlreg0;
        bool link_up = false;
 
        /* Call adapter stop to disable Tx/Rx and clear interrupts */
@@ -1366,6 +1691,15 @@ mac_reset_top:
        hw->mac.num_rar_entries = 128;
        hw->mac.ops.init_rx_addrs(hw);
 
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+               hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+               hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
+               IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+       }
+
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
+               ixgbe_setup_mux_ctl(hw);
+
        return status;
 }
 
@@ -1518,6 +1852,10 @@ static struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = {
        .read_i2c_sff8472       = &ixgbe_read_i2c_sff8472_generic, \
        .read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_generic, \
        .write_i2c_eeprom       = &ixgbe_write_i2c_eeprom_generic, \
+       .read_reg               = &ixgbe_read_phy_reg_generic, \
+       .write_reg              = &ixgbe_write_phy_reg_generic, \
+       .setup_link             = &ixgbe_setup_phy_link_generic, \
+       .set_phy_power          = &ixgbe_set_copper_phy_power, \
        .check_overtemp         = &ixgbe_tn_check_overtemp, \
        .get_firmware_version   = &ixgbe_get_phy_firmware_version_generic,
 
@@ -1525,9 +1863,6 @@ static struct ixgbe_phy_operations phy_ops_X550 = {
        X550_COMMON_PHY
        .init                   = NULL,
        .identify               = &ixgbe_identify_phy_generic,
-       .read_reg               = &ixgbe_read_phy_reg_generic,
-       .write_reg              = &ixgbe_write_phy_reg_generic,
-       .setup_link             = &ixgbe_setup_phy_link_generic,
        .read_i2c_combined      = &ixgbe_read_i2c_combined_generic,
        .write_i2c_combined     = &ixgbe_write_i2c_combined_generic,
 };
@@ -1536,9 +1871,14 @@ static struct ixgbe_phy_operations phy_ops_X550EM_x = {
        X550_COMMON_PHY
        .init                   = &ixgbe_init_phy_ops_X550em,
        .identify               = &ixgbe_identify_phy_x550em,
-       .read_reg               = NULL, /* defined later */
-       .write_reg              = NULL, /* defined later */
-       .setup_link             = NULL, /* defined later */
+};
+
+static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
+       IXGBE_MVALS_INIT(X550)
+};
+
+static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
+       IXGBE_MVALS_INIT(X550EM_x)
 };
 
 struct ixgbe_info ixgbe_X550_info = {
@@ -1548,6 +1888,7 @@ struct ixgbe_info ixgbe_X550_info = {
        .eeprom_ops             = &eeprom_ops_X550,
        .phy_ops                = &phy_ops_X550,
        .mbx_ops                = &mbx_ops_generic,
+       .mvals                  = ixgbe_mvals_X550,
 };
 
 struct ixgbe_info ixgbe_X550EM_x_info = {
@@ -1557,4 +1898,5 @@ struct ixgbe_info ixgbe_X550EM_x_info = {
        .eeprom_ops             = &eeprom_ops_X550EM_x,
        .phy_ops                = &phy_ops_X550EM_x,
        .mbx_ops                = &mbx_ops_generic,
+       .mvals                  = ixgbe_mvals_X550EM_x,
 };