@@ -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,58 @@
+#include "common.h"
+#include "stmmac_pcs.h"
+
+int dwmac_pcs_config(struct mac_device_info *hw, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ unsigned int reg_base)
+{
+ u32 val;
+
+ val = readl(hw->pcsr + GMAC_AN_CTRL(reg_base));
+
+ val |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN;
+
+ if (hw->ps)
+ val |= GMAC_AN_CTRL_SGMRAL;
+
+ writel(val, hw->pcsr + GMAC_AN_CTRL(reg_base));
+
+ return 0;
+}
+
+void dwmac_pcs_get_state(struct mac_device_info *hw,
+ struct phylink_link_state *state,
+ unsigned int reg_base)
+{
+ u32 val;
+
+ val = readl(hw->pcsr + GMAC_ANE_LPA(reg_base));
+
+ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ state->lp_advertising);
+
+ if (val & GMAC_ANE_FD) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ state->lp_advertising);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ state->lp_advertising);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+ state->lp_advertising);
+ }
+
+ if (val & GMAC_ANE_HD) {
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+ state->lp_advertising);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ state->lp_advertising);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ state->lp_advertising);
+ }
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
+ state->lp_advertising,
+ FIELD_GET(GMAC_ANE_PSE, val) & STMMAC_PCS_PAUSE);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ state->lp_advertising,
+ FIELD_GET(GMAC_ANE_PSE, val) & STMMAC_PCS_ASYM_PAUSE);
+}
@@ -137,4 +137,14 @@ static inline void dwmac_get_adv_lp(void __iomem *ioaddr, u32 reg,
adv_lp->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT;
}
+
+int dwmac_pcs_config(struct mac_device_info *hw, unsigned int neg_mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ unsigned int reg_base);
+
+void dwmac_pcs_get_state(struct mac_device_info *hw,
+ struct phylink_link_state *state,
+ unsigned int reg_base);
+
#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(), dwmac_ctrl_ane() and dwmac_get_adv_lp(). Rather than use these (which don't quite fit with phylink PCS, provide phylink PCS specific versions. 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 | 58 +++++++++++++++++++ .../net/ethernet/stmicro/stmmac/stmmac_pcs.h | 10 ++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c