Provide phylink with the autonegotiation capabilities for this PCS, and configure the PCS's AN settings according to phylink's requested requirements. This may cause regressions. Signed-off-by: Russell King (Oracle) --- .../net/ethernet/stmicro/stmmac/stmmac_pcs.c | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c index e2f531c11986..77d38936d898 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c @@ -2,6 +2,15 @@ #include "stmmac.h" #include "stmmac_pcs.h" +static unsigned int dwmac_integrated_pcs_inband_caps(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + if (interface != PHY_INTERFACE_MODE_SGMII) + return 0; + + return LINK_INBAND_ENABLE | LINK_INBAND_DISABLE; +} + static int dwmac_integrated_pcs_enable(struct phylink_pcs *pcs) { struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); @@ -32,13 +41,23 @@ static int dwmac_integrated_pcs_config(struct phylink_pcs *pcs, bool permit_pause_to_mac) { struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); - - dwmac_ctrl_ane(spcs->base, 0, 1, spcs->priv->hw->reverse_sgmii_enable); + void __iomem *an_control = spcs->base + GMAC_AN_CTRL(0); + u32 ctrl; + + ctrl = readl(an_control) & ~(GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_SGMRAL); + if (spcs->priv->hw->reverse_sgmii_enable) + ctrl |= GMAC_AN_CTRL_SGMRAL | GMAC_AN_CTRL_ANE; + else if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + ctrl |= GMAC_AN_CTRL_ANE; + else + ctrl |= GMAC_AN_CTRL_SGMRAL; + writel(ctrl, an_control); return 0; } static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = { + .pcs_inband_caps = dwmac_integrated_pcs_inband_caps, .pcs_enable = dwmac_integrated_pcs_enable, .pcs_disable = dwmac_integrated_pcs_disable, .pcs_get_state = dwmac_integrated_pcs_get_state, -- 2.47.3 Report if/when qcom-ethqos changes the PCS configuration. With phylink now setting the PCS configuration, there should be no need for drivers to change this. Signed-off-by: Russell King (Oracle) --- drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h index cda93894168e..e42a98162c2b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h @@ -109,6 +109,7 @@ static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, bool srgmi_ral) { u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); + u32 old = value; /* Enable and restart the Auto-Negotiation */ if (ane) @@ -122,6 +123,10 @@ static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, if (srgmi_ral) value |= GMAC_AN_CTRL_SGMRAL; + if (old != value) + pr_warn("dwmac: PCS configuration changed from phylink by glue, please report: 0x%08x -> 0x%08x\n", + old, value); + writel(value, ioaddr + GMAC_AN_CTRL(reg)); } #endif /* __STMMAC_PCS_H__ */ -- 2.47.3 Signed-off-by: Russell King (Oracle) --- drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 7 ++++++- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 7 ++++++- drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c | 6 ++++-- drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index a2ae136d2c0e..0d85902bafd0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -24,12 +24,17 @@ static int dwmac1000_pcs_init(struct stmmac_priv *priv) { + phy_interface_t mode; + if (!priv->dma_cap.pcs) return 0; + mode = PHY_INTERFACE_MODE_SGMII; + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE, GMAC_INT_DISABLE_PCSLINK | - GMAC_INT_DISABLE_PCSAN); + GMAC_INT_DISABLE_PCSAN, + &mode, 1); } static void dwmac1000_core_init(struct mac_device_info *hw, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index a4282fd7c3c7..af9a336a32e6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -24,11 +24,16 @@ static int dwmac4_pcs_init(struct stmmac_priv *priv) { + phy_interface_t mode; + if (!priv->dma_cap.pcs) return 0; + mode = PHY_INTERFACE_MODE_SGMII; + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE, - GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE); + GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE, + &mode, 1); } static void dwmac4_core_init(struct mac_device_info *hw, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c index 77d38936d898..5293c52cf7af 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c @@ -65,7 +65,8 @@ static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = { }; int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset, - u32 int_mask) + u32 int_mask, const phy_interface_t *modes, + int num) { struct stmmac_pcs *spcs; @@ -78,7 +79,8 @@ int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset, spcs->int_mask = int_mask; spcs->pcs.ops = &dwmac_integrated_pcs_ops; - __set_bit(PHY_INTERFACE_MODE_SGMII, spcs->pcs.supported_interfaces); + while (num--) + __set_bit(*modes++, spcs->pcs.supported_interfaces); priv->integrated_pcs = spcs; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h index e42a98162c2b..36da4dab4f8f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h @@ -63,7 +63,8 @@ phylink_pcs_to_stmmac_pcs(struct phylink_pcs *pcs) } int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset, - u32 int_mask); + u32 int_mask, const phy_interface_t *modes, + int num); /** * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR -- 2.47.3