From: "Russell King (Oracle)" Subject: [PATCH net-next 4/4] net: xpcs: add SGMII mode setting Add SGMII mode setting which configures whether XPCS immitates the MAC end of the link or the PHY end, and in the latter case, where the data for generating the link's configuration word comes from. Signed-off-by: Russell King (Oracle) --- drivers/net/pcs/pcs-xpcs.c | 37 +++++++++++++++++++------------------ drivers/net/pcs/pcs-xpcs.h | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 75ed8d535de2..14493cb61c85 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -676,11 +676,14 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, break; } - if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) { - /* Hardware requires it to be PHY side SGMII */ - tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII; - } else { + switch (xpcs->sgmii_mode) { + case DW_XPCS_SGMII_MODE_MAC: tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII; + break; + case DW_XPCS_SGMII_MODE_PHY_HW: + case DW_XPCS_SGMII_MODE_PHY_REG: + tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII; + break; } val |= FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, tx_conf); @@ -692,21 +695,18 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, val = 0; mask = DW_VR_MII_DIG_CTRL1_2G5_EN | DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; - /* MAC_AUTO_SW only applies for MAC-side SGMII. */ - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) - val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; - - /* PHY_MODE_CTRL only applies for PHY-side SGMII. When PHY_MODE_CTRL - * is set, the SGMII tx_config register bits 15 (link), 12 (duplex) - * and 11:10 (speed) sent is derived from hardware inputs to the XPCS. - * When clear, bit 15 comes from DW_VR_MII_AN_CTRL bit 4, bit 12 from - * MII_ADVERTISE bit 5, and bits 11:10 from MII_BMCR speed bits. In - * the latter case, some implementation documentatoin states that - * MII_ADVERTISE must be written last. - */ - if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) { - mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL; + switch (xpcs->sgmii_mode) { + case DW_XPCS_SGMII_MODE_MAC: + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; + break; + + case DW_XPCS_SGMII_MODE_PHY_HW: val |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL; + fallthrough; + case DW_XPCS_SGMII_MODE_PHY_REG: + mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL; + break; } ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val); @@ -1500,6 +1500,7 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev) if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) { xpcs->pcs.poll = false; xpcs->sgmii_10_100_8bit = DW_XPCS_SGMII_10_100_8BIT; + xpcs->sgmii_mode = DW_XPCS_SGMII_MODE_PHY_HW; } else { xpcs->need_reset = true; } diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 268a9be21c77..f1ba6d6a9ced 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -111,6 +111,25 @@ enum dw_xpcs_sgmii_10_100 { DW_XPCS_SGMII_10_100_8BIT }; +/* The SGMII mode: + * DW_XPCS_SGMII_MODE_MAC: the XPCS acts as a MAC, reading and acknowledging + * the config word. + * + * DW_XPCS_SGMII_MODE_PHY_HW: the XPCS acts as a PHY, deriving the tx_config + * bits 15 (link), 12 (duplex) and 11:10 (speed) from hardware inputs to the + * XPCS. + * + * DW_XPCS_SGMII_MODE_PHY_REG: the XPCS acts as a PHY, deriving the tx_config + * bit 15 comes from DW_VR_MII_AN_CTRL bit 4, bit 12 from MII_ADVERTISE bit 5, + * and bits 11:10 from MII_BMCR speed bits. In the latter case, some + * implementation documentatoin states that MII_ADVERTISE must be written last. + */ +enum dw_xpcs_sgmii_mode { + DW_XPCS_SGMII_MODE_MAC, /* XPCS is MAC on SGMII */ + DW_XPCS_SGMII_MODE_PHY_HW, /* XPCS is PHY, tx_config from hw */ + DW_XPCS_SGMII_MODE_PHY_REG, /* XPCS is PHY, tx_config from regs */ +}; + struct dw_xpcs { struct dw_xpcs_info info; const struct dw_xpcs_desc *desc; @@ -121,6 +140,7 @@ struct dw_xpcs { bool need_reset; /* Width of the MII MAC/XPCS interface in 100M and 10M modes */ enum dw_xpcs_sgmii_10_100 sgmii_10_100_8bit; + enum dw_xpcs_sgmii_mode sgmii_mode; u8 eee_mult_fact; }; -- 2.30.2