summaryrefslogtreecommitdiffstats
path: root/drivers/net/igb/e1000_82575.c
diff options
context:
space:
mode:
authorNick Nunley <nicholas.d.nunley@intel.com>2010-07-26 15:15:06 +0200
committerDavid S. Miller <davem@davemloft.net>2010-07-27 03:42:53 +0200
commit4085f746db1b7d6b292cf27cc713a13a1fcb2681 (patch)
treebab50788ad8fc71dbd570c665f9d7b189bf4b235 /drivers/net/igb/e1000_82575.c
parente1000e: Drop a useless statement (diff)
downloadlinux-4085f746db1b7d6b292cf27cc713a13a1fcb2681.tar.xz
linux-4085f746db1b7d6b292cf27cc713a13a1fcb2681.zip
igb: add support for SGMII-based MDIO PHYs
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>
Diffstat (limited to 'drivers/net/igb/e1000_82575.c')
-rw-r--r--drivers/net/igb/e1000_82575.c82
1 files changed, 65 insertions, 17 deletions
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 06251a9e9f1b..2971438bd873 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -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);