These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / ethernet / intel / igb / e1000_phy.c
index c1bb64d..23ec28f 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel(R) Gigabit Ethernet Linux driver
- * Copyright(c) 2007-2014 Intel Corporation.
+ * Copyright(c) 2007-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,
@@ -36,9 +36,6 @@ static s32  igb_set_master_slave_mode(struct e1000_hw *hw);
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] = {
        0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
-#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
-       (sizeof(e1000_m88_cable_length_table) / \
-       sizeof(e1000_m88_cable_length_table[0]))
 
 static const u16 e1000_igp_2_cable_length_table[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
@@ -49,9 +46,6 @@ static const u16 e1000_igp_2_cable_length_table[] = {
        60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
        83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
        104, 109, 114, 118, 121, 124};
-#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
-       (sizeof(e1000_igp_2_cable_length_table) / \
-        sizeof(e1000_igp_2_cable_length_table[0]))
 
 /**
  *  igb_check_reset_block - Check if PHY reset is blocked
@@ -1268,6 +1262,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        switch (hw->phy.id) {
                        case I347AT4_E_PHY_ID:
                        case M88E1112_E_PHY_ID:
+                       case M88E1543_E_PHY_ID:
+                       case M88E1512_E_PHY_ID:
                        case I210_I_PHY_ID:
                                reset_dsp = false;
                                break;
@@ -1276,9 +1272,9 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                                        reset_dsp = false;
                                break;
                        }
-                       if (!reset_dsp)
+                       if (!reset_dsp) {
                                hw_dbg("Link taking longer than expected.\n");
-                       else {
+                       else {
                                /* We didn't get link.
                                 * Reset the DSP and cross our fingers.
                                 */
@@ -1303,6 +1299,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        if (hw->phy.type != e1000_phy_m88 ||
            hw->phy.id == I347AT4_E_PHY_ID ||
            hw->phy.id == M88E1112_E_PHY_ID ||
+           hw->phy.id == M88E1543_E_PHY_ID ||
+           hw->phy.id == M88E1512_E_PHY_ID ||
            hw->phy.id == I210_I_PHY_ID)
                goto out;
 
@@ -1700,7 +1698,7 @@ s32 igb_get_cable_length_m88(struct e1000_hw *hw)
 
        index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-       if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+       if (index >= ARRAY_SIZE(e1000_m88_cable_length_table) - 1) {
                ret_val = -E1000_ERR_PHY;
                goto out;
        }
@@ -1743,6 +1741,7 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
                phy->cable_length = phy_data / (is_cm ? 100 : 1);
                break;
        case M88E1543_E_PHY_ID:
+       case M88E1512_E_PHY_ID:
        case I347AT4_E_PHY_ID:
                /* Remember the original page select and set it to 7 */
                ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
@@ -1796,7 +1795,7 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
 
                index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                        M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-               if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+               if (index >= ARRAY_SIZE(e1000_m88_cable_length_table) - 1) {
                        ret_val = -E1000_ERR_PHY;
                        goto out;
                }
@@ -1840,7 +1839,7 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw)
        s32 ret_val = 0;
        u16 phy_data, i, agc_value = 0;
        u16 cur_agc_index, max_agc_index = 0;
-       u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
+       u16 min_agc_index = ARRAY_SIZE(e1000_igp_2_cable_length_table) - 1;
        static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
                IGP02E1000_PHY_AGC_A,
                IGP02E1000_PHY_AGC_B,
@@ -1863,7 +1862,7 @@ s32 igb_get_cable_length_igp_2(struct e1000_hw *hw)
                                IGP02E1000_AGC_LENGTH_MASK;
 
                /* Array index bound check. */
-               if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
+               if ((cur_agc_index >= ARRAY_SIZE(e1000_igp_2_cable_length_table)) ||
                    (cur_agc_index == 0)) {
                        ret_val = -E1000_ERR_PHY;
                        goto out;
@@ -2194,6 +2193,90 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw)
        return 0;
 }
 
+/**
+ *  igb_initialize_M88E1512_phy - Initialize M88E1512 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize Marvel 1512 to work correctly with Avoton.
+ **/
+s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = 0;
+
+       /* Switch to PHY page 0xFF. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
+       if (ret_val)
+               goto out;
+
+       /* Switch to PHY page 0xFB. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
+       if (ret_val)
+               goto out;
+
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D);
+       if (ret_val)
+               goto out;
+
+       /* Switch to PHY page 0x12. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
+       if (ret_val)
+               goto out;
+
+       /* Change mode to SGMII-to-Copper */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
+       if (ret_val)
+               goto out;
+
+       /* Return the PHY to page 0. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
+       if (ret_val)
+               goto out;
+
+       ret_val = igb_phy_sw_reset(hw);
+       if (ret_val) {
+               hw_dbg("Error committing the PHY changes\n");
+               return ret_val;
+       }
+
+       /* msec_delay(1000); */
+       usleep_range(1000, 2000);
+out:
+       return ret_val;
+}
+
 /**
  * igb_power_up_phy_copper - Restore copper link in case of PHY power down
  * @hw: pointer to the HW structure