]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
igb: add support for SGMII-based MDIO PHYs
authorNick Nunley <nicholas.d.nunley@intel.com>
Mon, 26 Jul 2010 13:15:06 +0000 (13:15 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Jul 2010 01:42:53 +0000 (18:42 -0700)
This patch adds support for external MDIO PHYs, in addition to
the standard SFP support for SGMII PHYs over the I2C interface.

Signed-off-by: Nicholas Nunley <nicholas.d.nunley@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/igb/e1000_82575.c
drivers/net/igb/e1000_defines.h

index 06251a9e9f1b65711e2bfaf6367119a11f68dd6d..2971438bd8736331baa226c70ae8d2836c8879b3 100644 (file)
@@ -70,6 +70,35 @@ static const u16 e1000_82580_rxpbs_table[] =
 #define E1000_82580_RXPBS_TABLE_SIZE \
        (sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
 
+/**
+ *  igb_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to determine if the I2C pins are being used for I2C or as an
+ *  external MDIO interface since the two options are mutually exclusive.
+ **/
+static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw)
+{
+       u32 reg = 0;
+       bool ext_mdio = false;
+
+       switch (hw->mac.type) {
+       case e1000_82575:
+       case e1000_82576:
+               reg = rd32(E1000_MDIC);
+               ext_mdio = !!(reg & E1000_MDIC_DEST);
+               break;
+       case e1000_82580:
+       case e1000_i350:
+               reg = rd32(E1000_MDICNFG);
+               ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
+               break;
+       default:
+               break;
+       }
+       return ext_mdio;
+}
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
@@ -144,13 +173,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 
        wr32(E1000_CTRL_EXT, ctrl_ext);
 
-       /*
-        * if using i2c make certain the MDICNFG register is cleared to prevent
-        * communications from being misrouted to the mdic registers
-        */
-       if ((ctrl_ext & E1000_CTRL_I2C_ENA) && (hw->mac.type == e1000_82580))
-               wr32(E1000_MDICNFG, 0);
-
        /* Set mta register count */
        mac->mta_reg_count = 128;
        /* Set rar entry count */
@@ -229,18 +251,20 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
        phy->reset_delay_us      = 100;
 
        /* PHY function pointers */
-       if (igb_sgmii_active_82575(hw)) {
-               phy->ops.reset              = igb_phy_hw_reset_sgmii_82575;
-               phy->ops.read_reg           = igb_read_phy_reg_sgmii_82575;
-               phy->ops.write_reg          = igb_write_phy_reg_sgmii_82575;
+       if (igb_sgmii_active_82575(hw))
+               phy->ops.reset      = igb_phy_hw_reset_sgmii_82575;
+       else
+               phy->ops.reset      = igb_phy_hw_reset;
+
+       if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) {
+               phy->ops.read_reg   = igb_read_phy_reg_sgmii_82575;
+               phy->ops.write_reg  = igb_write_phy_reg_sgmii_82575;
        } else if (hw->mac.type >= e1000_82580) {
-               phy->ops.reset              = igb_phy_hw_reset;
-               phy->ops.read_reg           = igb_read_phy_reg_82580;
-               phy->ops.write_reg          = igb_write_phy_reg_82580;
+               phy->ops.read_reg   = igb_read_phy_reg_82580;
+               phy->ops.write_reg  = igb_write_phy_reg_82580;
        } else {
-               phy->ops.reset              = igb_phy_hw_reset;
-               phy->ops.read_reg           = igb_read_phy_reg_igp;
-               phy->ops.write_reg          = igb_write_phy_reg_igp;
+               phy->ops.read_reg   = igb_read_phy_reg_igp;
+               phy->ops.write_reg  = igb_write_phy_reg_igp;
        }
 
        /* set lan id */
@@ -400,6 +424,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
        s32  ret_val = 0;
        u16 phy_id;
        u32 ctrl_ext;
+       u32 mdic;
 
        /*
         * For SGMII PHYs, we try the list of possible addresses until
@@ -414,6 +439,29 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
                goto out;
        }
 
+       if (igb_sgmii_uses_mdio_82575(hw)) {
+               switch (hw->mac.type) {
+               case e1000_82575:
+               case e1000_82576:
+                       mdic = rd32(E1000_MDIC);
+                       mdic &= E1000_MDIC_PHY_MASK;
+                       phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
+                       break;
+               case e1000_82580:
+               case e1000_i350:
+                       mdic = rd32(E1000_MDICNFG);
+                       mdic &= E1000_MDICNFG_PHY_MASK;
+                       phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
+                       break;
+               default:
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+                       break;
+               }
+               ret_val = igb_get_phy_id(hw);
+               goto out;
+       }
+
        /* Power on sgmii phy if it is disabled */
        ctrl_ext = rd32(E1000_CTRL_EXT);
        wr32(E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
index 90bc29d7e182800b29ed7a507a92aa72daf3d936..1d4767f5f11076f6328d0e71ca3cb3644275d347 100644 (file)
 
 #define E1000_TIMINCA_16NS_SHIFT 24
 
+#define E1000_MDICNFG_EXT_MDIO    0x80000000      /* MDI ext/int destination */
+#define E1000_MDICNFG_COM_MDIO    0x40000000      /* MDI shared w/ lan 0 */
+#define E1000_MDICNFG_PHY_MASK    0x03E00000
+#define E1000_MDICNFG_PHY_SHIFT   21
+
 /* PCI Express Control */
 #define E1000_GCR_CMPL_TMOUT_MASK       0x0000F000
 #define E1000_GCR_CMPL_TMOUT_10ms       0x00001000
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
 
 /* MDI Control */
+#define E1000_MDIC_DATA_MASK 0x0000FFFF
+#define E1000_MDIC_REG_MASK  0x001F0000
 #define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK  0x03E00000
 #define E1000_MDIC_PHY_SHIFT 21
 #define E1000_MDIC_OP_WRITE  0x04000000
 #define E1000_MDIC_OP_READ   0x08000000
 #define E1000_MDIC_READY     0x10000000
+#define E1000_MDIC_INT_EN    0x20000000
 #define E1000_MDIC_ERROR     0x40000000
+#define E1000_MDIC_DEST      0x80000000
 
 /* SerDes Control */
 #define E1000_GEN_CTL_READY             0x80000000