summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2025-02-05 14:08:10 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2025-09-29 10:14:43 +0100
commitead56d602a3a3d060b017ff6d20860796e8e8712 (patch)
treeb9a8052d335a65d751b0b258ce4a8f6b4d7b49c1
parent71c5987e2c9414e8a9d575c9070b338fc1f88ae5 (diff)
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. This ties up all the register bits necessary to configure this mode into one control. Set this to PHY_HW mode for TXGBE. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/pcs/pcs-xpcs.c19
-rw-r--r--drivers/net/pcs/pcs-xpcs.h14
2 files changed, 25 insertions, 8 deletions
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 634c94bb61ad..92382a277605 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -697,12 +697,10 @@ 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 {
+ if (xpcs->sgmii_mode == DW_XPCS_SGMII_MODE_MAC)
tx_conf = DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII;
- }
+ else
+ tx_conf = DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII;
val |= FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, tx_conf);
@@ -713,12 +711,16 @@ 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;
- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
- val = DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
+ 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;
- if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID) {
+ case DW_XPCS_SGMII_MODE_PHY_HW:
mask |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
val |= DW_VR_MII_DIG_CTRL1_PHY_MODE_CTRL;
+ break;
}
ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, mask, val);
@@ -1507,6 +1509,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 96ee0868ad20..56e0ad8900e2 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -111,6 +111,19 @@ 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.
+ */
+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 */
+};
+
struct dw_xpcs {
struct dw_xpcs_info info;
const struct dw_xpcs_desc *desc;
@@ -122,6 +135,7 @@ struct dw_xpcs {
u8 eee_mult_fact;
/* 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;
};
int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg);