[PATCH net-next 3/9] net: sparx5/lan969x: add a helper for setting the MAC max frame length
From: Daniel Machon
Date: Thu Nov 05 2026 - 09:51:43 EST
The maximum frame length accepted by a port is set in the MAC_MAXLEN_CFG
register of its MAC. All ports have a 2G5 device, the 5G, 10G and 25G
ports also have a high speed device, and the lan969x RGMII ports have an
RGMII device instead. The register is currently written open-coded in
sparx5_port_init(), with a fixed length of 1518 bytes.
Add sparx5_port_max_len_set(), which sets the maximum frame length in the
devices of a port, and use it in sparx5_port_init(). To support the
RGMII devices, add the DEVRGMII_MAC_MAXLEN_CFG register, and make
lan969x_port_dev_mapping() return the RGMII device index for the RGMII
ports.
The helper is used to change the maximum frame length with the MTU, later
in this series.
No functional change intended.
Signed-off-by: Daniel Machon <daniel.machon@xxxxxxxxxxxxx>
---
.../ethernet/microchip/sparx5/lan969x/lan969x.c | 9 ++++
.../ethernet/microchip/sparx5/sparx5_main_regs.h | 11 +++++
.../net/ethernet/microchip/sparx5/sparx5_port.c | 50 ++++++++++++++++------
.../net/ethernet/microchip/sparx5/sparx5_port.h | 4 ++
4 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c
index c02499d1b297a..e8c30049b54cf 100644
--- a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c
@@ -180,6 +180,15 @@ static u32 lan969x_port_dev_mapping(struct sparx5 *sparx5, int port)
}
}
+ if (lan969x_port_is_rgmii(port)) {
+ switch (port) {
+ case 28:
+ return 0;
+ case 29:
+ return 1;
+ }
+ }
+
/* 2g5 port */
return port;
}
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
index df438be0ec552..5302c7686e207 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
@@ -8430,6 +8430,17 @@ extern const struct sparx5_regs *regs;
#define DEVRGMII_MAC_ENA_CFG_TX_ENA_GET(x)\
FIELD_GET(DEVRGMII_MAC_ENA_CFG_TX_ENA, x)
+/* LAN969X ONLY */
+/* DEV1G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */
+#define DEVRGMII_MAC_MAXLEN_CFG(t) \
+ __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 8, 0, 1, 4)
+
+#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN GENMASK(15, 0)
+#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN, x)
+#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN, x)
+
/* LAN969X ONLY */
/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG */
#define DEVRGMII_MAC_TAGS_CFG(t) \
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
index ef06bed3a9cc4..701d310df0ba6 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
@@ -613,6 +613,42 @@ static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
return 0;
}
+/* Set the maximum frame length accepted by the MAC of a port */
+void sparx5_port_max_len_set(struct sparx5 *sparx5,
+ struct sparx5_port *port,
+ u32 len)
+{
+ u32 pix = sparx5_port_dev_index(sparx5, port->portno);
+ const struct sparx5_ops *ops = sparx5->data->ops;
+ void __iomem *devinst;
+
+ if (ops->is_port_rgmii(port->portno)) {
+ spx5_rmw(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_SET(len),
+ DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN,
+ sparx5,
+ DEVRGMII_MAC_MAXLEN_CFG(pix));
+ return;
+ }
+
+ /* All other ports have a 2G5 (shadow) device */
+ spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(len),
+ DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
+ sparx5,
+ DEV2G5_MAC_MAXLEN_CFG(port->portno));
+
+ if (ops->is_port_2g5(port->portno))
+ return;
+
+ /* The MAXLEN_CFG register layout is shared by the high speed devices */
+ devinst = spx5_inst_get(sparx5,
+ sparx5_to_high_dev(sparx5, port->portno), pix);
+
+ spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(len),
+ DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
+ devinst,
+ DEV10G_MAC_MAXLEN_CFG(0));
+}
+
int sparx5_port_fwd_urg(struct sparx5 *sparx5, u32 speed)
{
u32 clk_period_ps = 1600; /* 625Mhz for now */
@@ -1068,18 +1104,15 @@ int sparx5_port_init(struct sparx5 *sparx5,
u32 pause_start = sparx5_wm_enc(6 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
u32 atop = sparx5_wm_enc(20 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
const struct sparx5_ops *ops = sparx5->data->ops;
- u32 devhigh = sparx5_to_high_dev(sparx5, port->portno);
u32 pix = sparx5_port_dev_index(sparx5, port->portno);
u32 pcs = sparx5_to_pcs_dev(sparx5, port->portno);
bool sd_pol = port->signd_active_high;
bool sd_sel = !port->signd_internal;
bool sd_ena = port->signd_enable;
u32 pause_stop = 0xFFF - 1; /* FC generate disabled */
- void __iomem *devinst;
void __iomem *pcsinst;
int err;
- devinst = spx5_inst_get(sparx5, devhigh, pix);
pcsinst = spx5_inst_get(sparx5, pcs, pix);
/* Set the mux port mode */
@@ -1119,10 +1152,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
return err;
/* Set Max Length */
- spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
- DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
- sparx5,
- DEV2G5_MAC_MAXLEN_CFG(port->portno));
+ sparx5_port_max_len_set(sparx5, port, ETH_MAXLEN);
/* 1G/2G5: Signal Detect configuration */
spx5_wr(DEV2G5_PCS1G_SD_CFG_SD_POL_SET(sd_pol) |
@@ -1171,12 +1201,6 @@ int sparx5_port_init(struct sparx5 *sparx5,
if (sparx5_is_baser(conf->portmode))
sparx5_dev_switch(sparx5, port->portno, true);
- /* Set Max Length */
- spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
- DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
- devinst,
- DEV10G_MAC_MAXLEN_CFG(0));
-
/* Handle Signal Detect in 10G PCS */
spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) |
PCS10G_BR_PCS_SD_CFG_SD_SEL_SET(sd_sel) |
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
index c8a37468a3d1d..912f97a506768 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
@@ -88,6 +88,10 @@ int sparx5_port_init(struct sparx5 *sparx5,
struct sparx5_port *spx5_port,
struct sparx5_port_config *conf);
+void sparx5_port_max_len_set(struct sparx5 *sparx5,
+ struct sparx5_port *port,
+ u32 len);
+
int sparx5_port_config(struct sparx5 *sparx5,
struct sparx5_port *spx5_port,
struct sparx5_port_config *conf);
--
2.34.1