[PATCH net-next v4 05/10] net: stmmac: mediatek: simplify TX/RX delay handling in mt2712_set_delay
Louis-Alexis Eyraud
louisalexis.eyraud at collabora.com
Tue Nov 3 02:12:10 PST 2026
The mt2712_set_delay function modifies at its beginning the TX and RX
internal delay variables, located in the driver data, by dividing
them by a constant (170 for RGMII, 550 for MII/RMII) and restores their
original values by multiplying them again at the function end. It is
done in order to convert them into a step value, used by the hardware
registers for setting these delays.
But this is rather pointless to modify the driver data for that, while
it could be done locally in the function. The original delay values
cannot be used anymore (if needed) during mt2712_set_delay processing.
Finally, they are altered after the function call if they are not a
multiple of the delay stage divider.
So, simplify these delay variable handling by using local variables to
convert them into the register value and use those in the write calls.
Also, remove the two private conversion functions, that are not useful
anymore and add definitions for MT2712 RX/TX delay maximum and divider
values.
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud at collabora.com>
---
.../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 140 +++++++++------------
1 file changed, 62 insertions(+), 78 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index ac473222213f..cda3f3edde39 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -36,6 +36,11 @@
#define ETH_FINE_DLY_GTXC BIT(1)
#define ETH_FINE_DLY_RXC BIT(0)
+#define MT2712_MII_DLY_STAGE_DIV 550 /* 550ps per stage */
+#define MT2712_MII_DELAY_MAX 17600 /* 32 x 550ps */
+#define MT2712_RGMII_DLY_STAGE_DIV 170 /* 170ps per stage */
+#define MT2712_RGMII_DELAY_MAX 5440 /* 32 x 170ps */
+
/* Peri Configuration register for mt8195 */
#define MT8195_PERI_ETH_CTRL0 0xFD0
#define MT8195_RMII_CLK_SRC_INTERNAL BIT(28)
@@ -129,86 +134,54 @@ static int mt2712_set_interface(struct mediatek_dwmac_plat_data *plat,
return 0;
}
-static void mt2712_delay_ps2stage(struct mediatek_dwmac_plat_data *plat)
-{
- struct mac_delay_struct *mac_delay = &plat->mac_delay;
-
- switch (plat->phy_mode) {
- case PHY_INTERFACE_MODE_MII:
- case PHY_INTERFACE_MODE_RMII:
- /* 550ps per stage for MII/RMII */
- mac_delay->tx_delay /= 550;
- mac_delay->rx_delay /= 550;
- break;
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_ID:
- /* 170ps per stage for RGMII */
- mac_delay->tx_delay /= 170;
- mac_delay->rx_delay /= 170;
- break;
- default:
- dev_err(plat->dev, "phy interface not supported\n");
- break;
- }
-}
-
-static void mt2712_delay_stage2ps(struct mediatek_dwmac_plat_data *plat)
-{
- struct mac_delay_struct *mac_delay = &plat->mac_delay;
-
- switch (plat->phy_mode) {
- case PHY_INTERFACE_MODE_MII:
- case PHY_INTERFACE_MODE_RMII:
- /* 550ps per stage for MII/RMII */
- mac_delay->tx_delay *= 550;
- mac_delay->rx_delay *= 550;
- break;
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_ID:
- /* 170ps per stage for RGMII */
- mac_delay->tx_delay *= 170;
- mac_delay->rx_delay *= 170;
- break;
- default:
- dev_err(plat->dev, "phy interface not supported\n");
- break;
- }
-}
-
static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
{
struct mac_delay_struct *mac_delay = &plat->mac_delay;
- u32 delay_val = 0, fine_val = 0;
-
- mt2712_delay_ps2stage(plat);
+ u32 rx_delay_stage_val, tx_delay_stage_val;
+ u32 delay_val = 0;
+ u32 fine_val = 0;
switch (plat->phy_mode) {
case PHY_INTERFACE_MODE_MII:
- delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->tx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->tx_delay);
+ rx_delay_stage_val = mac_delay->rx_delay
+ / MT2712_MII_DLY_STAGE_DIV;
+ tx_delay_stage_val = mac_delay->tx_delay
+ / MT2712_MII_DLY_STAGE_DIV;
+
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE,
+ !!tx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES,
+ tx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->tx_inv);
- delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE,
+ !!rx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES,
+ rx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);
break;
case PHY_INTERFACE_MODE_RMII:
+ rx_delay_stage_val = mac_delay->rx_delay
+ / MT2712_MII_DLY_STAGE_DIV;
+ tx_delay_stage_val = mac_delay->tx_delay
+ / MT2712_MII_DLY_STAGE_DIV;
+
if (plat->rmii_clk_from_mac) {
/* case 1: mac provides the rmii reference clock,
* and the clock output to TXC pin.
* The egress timing can be adjusted by GTXC delay macro circuit.
* The ingress timing can be adjusted by TXC delay macro circuit.
*/
- delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->rx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->rx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE,
+ !!rx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES,
+ rx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->rx_inv);
- delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE, !!mac_delay->tx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES, mac_delay->tx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE,
+ !!tx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES,
+ tx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_GTXC_INV, mac_delay->tx_inv);
} else {
/* case 2: the rmii reference clock is from external phy,
@@ -222,16 +195,20 @@ static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
* to RXC pin, the reference clock will be adjusted
* by RXC delay macro circuit.
*/
- delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE,
+ !!rx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES,
+ rx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);
} else {
/* the rmii reference clock from outside is connected
* to TXC pin, the reference clock will be adjusted
* by TXC delay macro circuit.
*/
- delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE, !!mac_delay->rx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES, mac_delay->rx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_ENABLE,
+ !!rx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_TXC_STAGES,
+ rx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_TXC_INV, mac_delay->rx_inv);
}
/* tx_inv will inverse the tx clock inside mac relateive to
@@ -246,14 +223,23 @@ static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
+ rx_delay_stage_val = mac_delay->rx_delay
+ / MT2712_RGMII_DLY_STAGE_DIV;
+ tx_delay_stage_val = mac_delay->tx_delay
+ / MT2712_RGMII_DLY_STAGE_DIV;
+
fine_val = ETH_FINE_DLY_GTXC | ETH_FINE_DLY_RXC;
- delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE, !!mac_delay->tx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES, mac_delay->tx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_GTXC_ENABLE,
+ !!tx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_GTXC_STAGES,
+ tx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_GTXC_INV, mac_delay->tx_inv);
- delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE, !!mac_delay->rx_delay);
- delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES, mac_delay->rx_delay);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_ENABLE,
+ !!rx_delay_stage_val);
+ delay_val |= FIELD_PREP(ETH_DLY_RXC_STAGES,
+ rx_delay_stage_val);
delay_val |= FIELD_PREP(ETH_DLY_RXC_INV, mac_delay->rx_inv);
break;
default:
@@ -263,19 +249,17 @@ static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
regmap_write(plat->peri_regmap, PERI_ETH_DLY, delay_val);
regmap_write(plat->peri_regmap, PERI_ETH_DLY_FINE, fine_val);
- mt2712_delay_stage2ps(plat);
-
return 0;
}
static const struct mediatek_dwmac_variant mt2712_gmac_variant = {
- .dwmac_set_phy_interface = mt2712_set_interface,
- .dwmac_set_delay = mt2712_set_delay,
- .clk_list = mt2712_dwmac_clk_l,
- .num_clks = ARRAY_SIZE(mt2712_dwmac_clk_l),
- .rx_delay_max = 17600,
- .tx_delay_max = 17600,
- .dma_bit_mask = 33,
+ .dwmac_set_phy_interface = mt2712_set_interface,
+ .dwmac_set_delay = mt2712_set_delay,
+ .clk_list = mt2712_dwmac_clk_l,
+ .num_clks = ARRAY_SIZE(mt2712_dwmac_clk_l),
+ .rx_delay_max = MT2712_MII_DELAY_MAX,
+ .tx_delay_max = MT2712_MII_DELAY_MAX,
+ .dma_bit_mask = 33,
};
static int mt8195_set_interface(struct mediatek_dwmac_plat_data *plat,
--
2.56.0
More information about the linux-arm-kernel
mailing list