@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \
dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
- stmmac_xdp.o stmmac_est.o \
+ stmmac_xdp.o stmmac_est.o stmmac_pcs.o \
$(stmmac-y)
stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
new file mode 100644
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include "stmmac.h"
+#include "stmmac_pcs.h"
+
+static void __dwmac_ctrl_ane(struct stmmac_pcs *spcs, bool ane, bool srgmi_ral,
+ bool loopback)
+
+{
+ u32 val;
+
+ val = readl(spcs->pcs_base + GMAC_AN_CTRL(0));
+
+ /* Enable and restart the Auto-Negotiation */
+ if (ane)
+ val |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN;
+ else
+ val &= ~GMAC_AN_CTRL_ANE;
+
+ /* In case of MAC-2-MAC connection, block is configured to operate
+ * according to MAC conf register.
+ */
+ if (srgmi_ral)
+ val |= GMAC_AN_CTRL_SGMRAL;
+
+ if (loopback)
+ val |= GMAC_AN_CTRL_ELE;
+ else
+ val &= ~GMAC_AN_CTRL_ELE;
+
+ writel(val, spcs->pcs_base + GMAC_AN_CTRL(0));
+}
+
+int dwmac_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs);
+
+ /* The RGMII interface does not have the GMAC_AN_CTRL register */
+ if (phy_interface_mode_is_rgmii(spcs->priv->plat->mac_interface))
+ return 0;
+
+ __dwmac_ctrl_ane(spcs, true, spcs->priv->hw->ps, false);
+
+ return 0;
+}
@@ -46,6 +46,19 @@
#define GMAC_ANE_RFE_SHIFT 12
#define GMAC_ANE_ACK BIT(14)
+/* MAC specific status - for RGMII and SGMII. These appear as
+ * GMAC_RGSMIIIS[15:0] and GMAC_PHYIF_CONTROL_STATUS[31:16]
+ */
+#define GMAC_RS_STAT_LNKMOD BIT(0)
+#define GMAC_RS_STAT_SPEED GENMASK(2, 1)
+#define GMAC_RS_STAT_LNKSTS BIT(3)
+#define GMAC_RS_STAT_JABTO BIT(4)
+#define GMAC_RS_STAT_FALSECARDET BIT(5)
+
+#define GMAC_RS_STAT_SPEED_125 2
+#define GMAC_RS_STAT_SPEED_25 1
+#define GMAC_RS_STAT_SPEED_2_5 0
+
/**
* dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR
* @ioaddr: IO registers pointer
@@ -109,4 +122,41 @@ static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane,
writel(value, ioaddr + GMAC_AN_CTRL(reg));
}
+
+static inline bool dwmac_rs_decode_stat(struct phylink_link_state *state,
+ uint16_t rs_stat)
+{
+ unsigned int speed;
+
+ state->link = !!(rs_stat & GMAC_RS_STAT_LNKSTS);
+ if (!state->link)
+ return false;
+
+ speed = FIELD_GET(GMAC_RS_STAT_SPEED, rs_stat);
+ switch (speed) {
+ case GMAC_RS_STAT_SPEED_125:
+ state->speed = SPEED_1000;
+ break;
+ case GMAC_RS_STAT_SPEED_25:
+ state->speed = SPEED_100;
+ break;
+ case GMAC_RS_STAT_SPEED_2_5:
+ state->speed = SPEED_10;
+ break;
+ default:
+ state->link = false;
+ return false;
+ }
+
+ state->duplex = rs_stat & GMAC_RS_STAT_LNKMOD ?
+ DUPLEX_FULL : DUPLEX_HALF;
+
+ return true;
+}
+
+int dwmac_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac);
+
#endif /* __STMMAC_PCS_H__ */
There are some common operations shared between the dwmac hwifs, the only difference is where they are located within the device. These are already present in the form of dwmac_rane() and dwmac_ctrl_ane(). Rather than use these (which don't quite fit with phylink PCS, provide phylink PCS specific versions. Also provide an implementation to parse the RSGMII status register. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_pcs.c | 47 +++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_pcs.h | 50 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c