Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4085f746 authored by Nick Nunley's avatar Nick Nunley Committed by David S. Miller
Browse files

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: default avatarNicholas Nunley <nicholas.d.nunley@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ea7afd31
Loading
Loading
Loading
Loading
+65 −17
Original line number Diff line number Diff line
@@ -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,16 +251,18 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
	phy->reset_delay_us      = 100;

	/* PHY function pointers */
	if (igb_sgmii_active_82575(hw)) {
	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;
	} 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;
	}
@@ -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);
+10 −0
Original line number Diff line number Diff line
@@ -468,6 +468,11 @@

#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
@@ -698,12 +703,17 @@
#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