summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-03-30 17:36:52 -0700
committerJakub Kicinski <kuba@kernel.org>2026-03-30 17:36:52 -0700
commit0fb03e7038e4f91d44776021ce301af8d4efe0ce (patch)
treeca13c61b6846d8d57c74a218f21a9ec37034a2ee
parent911e2c050963ccf239faec6ae9dee0f5e8f1cc5c (diff)
parent7f9f301660051353282e579affcd40e7075ab223 (diff)
Merge branch 'net-stmmac-qcom-ethqos-more-cleanups'davem/net-next/maindavem/net-next/HEAD
Russell King says: ==================== net: stmmac: qcom-ethqos: more cleanups Further cleanups to qcom-ethqos, mainly concentrating on the RGMII code, making it clearer what the differences are for each speed, thus making the code more readable. I'm still not really happy with this. The speed specific configuration remains split between ethqos_fix_mac_speed_rgmii() and ethqos_rgmii_macro_init(), where the latter is only ever called from the former. So, I think further work is needed here - maybe it needs restructuring into the various componenet parts of the RGMII block? ==================== Link: https://patch.msgid.link/acZDEg9wdjhBTHlL@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c220
1 files changed, 87 insertions, 133 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 3ccf20fdf52a..ad3a983d2a08 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -100,9 +100,6 @@ struct ethqos_emac_driver_data {
struct qcom_ethqos {
struct platform_device *pdev;
void __iomem *rgmii_base;
- void (*configure_func)(struct qcom_ethqos *ethqos,
- phy_interface_t interface, int speed);
-
struct clk *link_clk;
struct phy *serdes_phy;
phy_interface_t phy_mode;
@@ -377,157 +374,126 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed)
{
struct device *dev = &ethqos->pdev->dev;
- int phase_shift;
- int loopback;
-
- /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
- if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
- ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
- phase_shift = 0;
- else
- phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
+ unsigned int prg_rclk_dly, loopback;
+ unsigned int phase_shift;
/* Disable loopback mode */
rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
RGMII_IO_MACRO_CONFIG2);
- /* Determine if this platform wants loopback enabled after programming */
- if (ethqos->rgmii_config_loopback_en)
- loopback = RGMII_CONFIG_LOOPBACK_EN;
- else
- loopback = 0;
-
/* Select RGMII, write 0 to interface select */
rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG);
- switch (speed) {
- case SPEED_1000:
- rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE,
- RGMII_IO_MACRO_CONFIG);
+ if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) {
+ dev_err(dev, "Invalid speed %d\n", speed);
+ return -EINVAL;
+ }
+
+ rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
+
+ if (speed == SPEED_1000) {
rgmii_clrmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
RGMII_IO_MACRO_CONFIG);
rgmii_setmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
RGMII_IO_MACRO_CONFIG);
rgmii_setmask(ethqos, RGMII_CONFIG_PROG_SWAP,
RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
- RGMII_IO_MACRO_CONFIG2);
-
- rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- phase_shift, RGMII_IO_MACRO_CONFIG2);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
- RGMII_IO_MACRO_CONFIG2);
- rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- RGMII_IO_MACRO_CONFIG2);
-
- /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns,
- * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns
- */
- if (ethqos->has_emac_ge_3) {
- /* 0.9 ns */
- rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
- FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY,
- 115), SDCC_HC_REG_DDR_CONFIG);
- } else {
- /* 1.8 ns */
- rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
- FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY,
- 57), SDCC_HC_REG_DDR_CONFIG);
- }
- rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
- SDCC_HC_REG_DDR_CONFIG);
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- loopback, RGMII_IO_MACRO_CONFIG);
- break;
-
- case SPEED_100:
- rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE,
- RGMII_IO_MACRO_CONFIG);
+ } else {
rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
RGMII_IO_MACRO_CONFIG);
rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
RGMII_IO_MACRO_CONFIG);
rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP,
RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
- RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- phase_shift, RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
- FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1),
- RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
- RGMII_IO_MACRO_CONFIG2);
+ }
- if (ethqos->has_emac_ge_3)
- rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- RGMII_IO_MACRO_CONFIG2);
- else
- rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- RGMII_IO_MACRO_CONFIG2);
+ rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
+ RGMII_IO_MACRO_CONFIG2);
- /* Write 0x5 to PRG_RCLK_DLY_CODE */
- rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
- FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
- 5), SDCC_HC_REG_DDR_CONFIG);
- rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
- SDCC_HC_REG_DDR_CONFIG);
- rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
- SDCC_HC_REG_DDR_CONFIG);
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- loopback, RGMII_IO_MACRO_CONFIG);
- break;
+ /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
+ if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
+ ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
+ phase_shift = 0;
+ else
+ phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
- case SPEED_10:
- rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE,
- RGMII_IO_MACRO_CONFIG);
- rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
- RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
- RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP,
+ rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, phase_shift,
+ RGMII_IO_MACRO_CONFIG2);
+
+ if (speed == SPEED_100)
+ rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
+ FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_2, 1),
RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
- RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- phase_shift, RGMII_IO_MACRO_CONFIG2);
+ else if (speed == SPEED_10)
rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
FIELD_PREP(RGMII_CONFIG_MAX_SPD_PRG_9, 19),
RGMII_IO_MACRO_CONFIG);
- rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
+
+ rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
+ RGMII_IO_MACRO_CONFIG2);
+
+ if (speed == SPEED_1000 || ethqos->has_emac_ge_3)
+ rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_IO_MACRO_CONFIG2);
+ else
+ rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
- if (ethqos->has_emac_ge_3)
- rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- RGMII_IO_MACRO_CONFIG2);
- else
- rgmii_clrmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- RGMII_IO_MACRO_CONFIG2);
+
+ if (speed != SPEED_1000) {
/* Write 0x5 to PRG_RCLK_DLY_CODE */
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
FIELD_PREP(SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
5), SDCC_HC_REG_DDR_CONFIG);
+
rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
SDCC_HC_REG_DDR_CONFIG);
+
rgmii_setmask(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
SDCC_HC_REG_DDR_CONFIG);
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- loopback, RGMII_IO_MACRO_CONFIG);
- break;
- default:
- dev_err(dev, "Invalid speed %d\n", speed);
- return -EINVAL;
+ } else {
+ /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT /
+ * (2 * RX delay ns),
+ * in practice this becomes PRG_RCLK_DLY = 52 * 4 /
+ * (2 * RX delay ns)
+ */
+ if (ethqos->has_emac_ge_3) {
+ /* 0.9 ns */
+ prg_rclk_dly = 115;
+ } else {
+ /* 1.8 ns */
+ prg_rclk_dly = 57;
+ }
+
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
+ FIELD_PREP(SDCC_DDR_CONFIG_PRG_RCLK_DLY,
+ prg_rclk_dly), SDCC_HC_REG_DDR_CONFIG);
+
+ rgmii_setmask(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
+ SDCC_HC_REG_DDR_CONFIG);
}
+ if (ethqos->rgmii_config_loopback_en)
+ loopback = RGMII_CONFIG_LOOPBACK_EN;
+ else
+ loopback = 0;
+
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback,
+ RGMII_IO_MACRO_CONFIG);
+
return 0;
}
-static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos,
- phy_interface_t interface, int speed)
+static void ethqos_fix_mac_speed_rgmii(void *bsp_priv,
+ phy_interface_t interface, int speed,
+ unsigned int mode)
{
- struct device *dev = &ethqos->pdev->dev;
+ struct qcom_ethqos *ethqos = bsp_priv;
+ struct device *dev;
unsigned int i;
u32 val;
+ dev = &ethqos->pdev->dev;
+
/* Reset to POR values and enable clk */
for (i = 0; i < ethqos->num_rgmii_por; i++)
rgmii_writel(ethqos, ethqos->rgmii_por[i].value,
@@ -590,19 +556,22 @@ static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos,
ethqos_rgmii_macro_init(ethqos, speed);
}
-static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable)
+static void ethqos_pcs_set_inband(struct qcom_ethqos *ethqos, bool enable)
{
+ struct net_device *dev = platform_get_drvdata(ethqos->pdev);
+ struct stmmac_priv *priv = netdev_priv(dev);
+
stmmac_pcs_ctrl_ane(priv, enable, 0);
}
/* On interface toggle MAC registers gets reset.
* Configure MAC block for SGMII on ethernet phy link up
*/
-static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos,
- phy_interface_t interface, int speed)
+static void ethqos_fix_mac_speed_sgmii(void *bsp_priv,
+ phy_interface_t interface, int speed,
+ unsigned int mode)
{
- struct net_device *dev = platform_get_drvdata(ethqos->pdev);
- struct stmmac_priv *priv = netdev_priv(dev);
+ struct qcom_ethqos *ethqos = bsp_priv;
switch (speed) {
case SPEED_2500:
@@ -620,21 +589,7 @@ static void ethqos_configure_sgmii(struct qcom_ethqos *ethqos,
break;
}
- ethqos_pcs_set_inband(priv, interface == PHY_INTERFACE_MODE_SGMII);
-}
-
-static void ethqos_configure(struct qcom_ethqos *ethqos,
- phy_interface_t interface, int speed)
-{
- return ethqos->configure_func(ethqos, interface, speed);
-}
-
-static void ethqos_fix_mac_speed(void *priv, phy_interface_t interface,
- int speed, unsigned int mode)
-{
- struct qcom_ethqos *ethqos = priv;
-
- ethqos_configure(ethqos, interface, speed);
+ ethqos_pcs_set_inband(ethqos, interface == PHY_INTERFACE_MODE_SGMII);
}
static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
@@ -693,7 +648,7 @@ static int ethqos_clks_config(void *priv, bool enabled)
/* Enable functional clock to prevent DMA reset to timeout due
* to lacking PHY clock after the hardware block has been power
* cycled. The actual configuration will be adjusted once
- * ethqos_fix_mac_speed() is invoked.
+ * ethqos' fix_mac_speed() method is invoked.
*/
qcom_ethqos_set_sgmii_loopback(ethqos, true);
ethqos_set_func_clk_en(ethqos);
@@ -759,11 +714,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- ethqos->configure_func = ethqos_configure_rgmii;
+ plat_dat->fix_mac_speed = ethqos_fix_mac_speed_rgmii;
break;
case PHY_INTERFACE_MODE_2500BASEX:
case PHY_INTERFACE_MODE_SGMII:
- ethqos->configure_func = ethqos_configure_sgmii;
+ plat_dat->fix_mac_speed = ethqos_fix_mac_speed_sgmii;
plat_dat->mac_finish = ethqos_mac_finish_serdes;
break;
default:
@@ -811,7 +766,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->bsp_priv = ethqos;
plat_dat->set_clk_tx_rate = ethqos_set_clk_tx_rate;
- plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
plat_dat->dump_debug_regs = rgmii_dump;
plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config;
plat_dat->core_type = DWMAC_CORE_GMAC4;