From 16e03235d51b016cbb9b2265b77f041b57b1ed54 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:00 +0100 Subject: [PATCH 01/11] net: stmmac: mdio: provide address register formatter Rather than duplicating the logic for filling the PA (MDIO address), GR (MDIO register/devad), CR (clock range) and GB (busy) fields of the address register in four locations, provide a helper to do this. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8ns-00000001voU-0S7b@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 0a302b711bc2..c305c202055a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -229,6 +229,26 @@ static int stmmac_xgmac2_mdio_write_c45(struct mii_bus *bus, int phyaddr, phydata); } +/** + * stmmac_mdio_format_addr() - format the address register + * @priv: struct stmmac_priv pointer + * @pa: 5-bit MDIO package address + * @gr: 5-bit MDIO register address (C22) or MDIO device address (C45) + * + * Return: formatted address register + */ +static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, + unsigned int pa, unsigned int gr) +{ + const struct mii_regs *mii_regs = &priv->hw->mii; + + return ((pa << mii_regs->addr_shift) & mii_regs->addr_mask) | + ((gr << mii_regs->reg_shift) & mii_regs->reg_mask) | + ((priv->clk_csr << mii_regs->clk_csr_shift) & + mii_regs->clk_csr_mask) | + MII_BUSY; +} + static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) { unsigned int mii_address = priv->hw->mii.addr; @@ -263,18 +283,14 @@ static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - u32 value = MII_BUSY; int data = 0; + u32 value; data = pm_runtime_resume_and_get(priv->device); if (data < 0) return data; - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; + value = stmmac_mdio_format_addr(priv, phyaddr, phyreg); if (priv->plat->has_gmac4) value |= MII_GMAC4_READ; @@ -300,20 +316,16 @@ static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - u32 value = MII_BUSY; int data = 0; + u32 value; data = pm_runtime_resume_and_get(priv->device); if (data < 0) return data; - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; + value = stmmac_mdio_format_addr(priv, phyaddr, devad); value |= MII_GMAC4_READ; value |= MII_GMAC4_C45E; - value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; @@ -357,18 +369,13 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, { struct stmmac_priv *priv = netdev_priv(bus->priv); int ret, data = phydata; - u32 value = MII_BUSY; + u32 value; ret = pm_runtime_resume_and_get(priv->device); if (ret < 0) return ret; - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; - - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; + value = stmmac_mdio_format_addr(priv, phyaddr, phyreg); if (priv->plat->has_gmac4) value |= MII_GMAC4_WRITE; else @@ -395,21 +402,15 @@ static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr, { struct stmmac_priv *priv = netdev_priv(bus->priv); int ret, data = phydata; - u32 value = MII_BUSY; + u32 value; ret = pm_runtime_resume_and_get(priv->device); if (ret < 0) return ret; - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - + value = stmmac_mdio_format_addr(priv, phyaddr, devad); value |= MII_GMAC4_WRITE; value |= MII_GMAC4_C45E; - value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; From 9eb633ad1d69930e7ddc9d86bdc30700e2b794eb Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:05 +0100 Subject: [PATCH 02/11] net: stmmac: mdio: provide stmmac_mdio_wait() All the readl_poll_timeout()s follow the same pattern - test a register for a bit being clear every 100us, and timeout after 10ms returning -EBUSY. Wrap this up into a function to avoid duplicating this. This slightly changes the return value for stmmac_mdio_write() if the second readl_poll_timeout() fails - rather than returning -ETIMEDOUT we return -EBUSY matching the stmmac_mdio_read() behaviour. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8nx-00000001voa-0tJ0@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 70 +++++++++---------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index c305c202055a..6acce54b5d55 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -45,6 +45,16 @@ #define MII_XGMAC_PA_SHIFT 16 #define MII_XGMAC_DA_SHIFT 21 +static int stmmac_mdio_wait(void __iomem *reg, u32 mask) +{ + u32 v; + + if (readl_poll_timeout(reg, v, !(v & mask), 100, 10000)) + return -EBUSY; + + return 0; +} + static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr, int devad, int phyreg, u32 *hw_addr) { @@ -83,7 +93,6 @@ static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 tmp; int ret; ret = pm_runtime_resume_and_get(priv->device); @@ -91,33 +100,27 @@ static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, return ret; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) & priv->hw->mii.clk_csr_mask; value |= MII_XGMAC_READ; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Set the MII address register to read */ writel(addr, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_data); /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Read the data from the MII data register */ ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0); @@ -160,7 +163,6 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 tmp; int ret; ret = pm_runtime_resume_and_get(priv->device); @@ -168,11 +170,9 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, return ret; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) & priv->hw->mii.clk_csr_mask; @@ -180,19 +180,16 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, value |= MII_XGMAC_WRITE; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Set the MII address register to write */ writel(addr, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_data); /* Wait until any existing MII operation is complete */ - ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000); + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); err_disable_clks: pm_runtime_put(priv->device); @@ -253,18 +250,18 @@ static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 v; + int ret; - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); + if (ret) + return ret; writel(data, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_address); - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); + if (ret) + return ret; /* Read the data from the MII data register */ return readl(priv->ioaddr + mii_data) & MII_DATA_MASK; @@ -340,20 +337,19 @@ static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value) { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 v; + int ret; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); + if (ret) + return ret; /* Set the MII address register to write */ writel(data, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_address); /* Wait until any existing MII operation is complete */ - return readl_poll_timeout(priv->ioaddr + mii_address, v, - !(v & MII_BUSY), 100, 10000); + return stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); } /** From 6717746f33abcd12a64f4cf609af19acb3e529ba Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:10 +0100 Subject: [PATCH 03/11] net: stmmac: mdio: provide priv->gmii_address_bus_config Provide a pre-formatted value for the MDIO address register fields which remain constant across the various different transactions rather than recreating the register value from scratch every time. Currently, we only do this for the CR (clock range) field. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8o2-00000001vog-1LyK@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 78d6b3737a26..4d5577935b13 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -290,6 +290,7 @@ struct stmmac_priv { int wolopts; int wol_irq; int clk_csr; + u32 gmii_address_bus_config; struct timer_list eee_ctrl_timer; int lpi_irq; u32 tx_lpi_timer; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 6acce54b5d55..4294262c208d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -104,9 +104,7 @@ static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, if (ret) goto err_disable_clks; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - value |= MII_XGMAC_READ; + value |= priv->gmii_address_bus_config | MII_XGMAC_READ; /* Wait until any existing MII operation is complete */ ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); @@ -174,10 +172,7 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, if (ret) goto err_disable_clks; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - value |= phydata; - value |= MII_XGMAC_WRITE; + value |= priv->gmii_address_bus_config | phydata | MII_XGMAC_WRITE; /* Wait until any existing MII operation is complete */ ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); @@ -241,8 +236,7 @@ static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, return ((pa << mii_regs->addr_shift) & mii_regs->addr_mask) | ((gr << mii_regs->reg_shift) & mii_regs->reg_mask) | - ((priv->clk_csr << mii_regs->clk_csr_shift) & - mii_regs->clk_csr_mask) | + priv->gmii_address_bus_config | MII_BUSY; } @@ -517,6 +511,18 @@ void stmmac_pcs_clean(struct net_device *ndev) priv->hw->xpcs = NULL; } +static void stmmac_mdio_bus_config(struct stmmac_priv *priv, u32 value) +{ + value <<= priv->hw->mii.clk_csr_shift; + + if (value & ~priv->hw->mii.clk_csr_mask) + dev_warn(priv->device, + "clk_csr value out of range (0x%08x exceeds mask 0x%08x), truncating\n", + value, priv->hw->mii.clk_csr_mask); + + priv->gmii_address_bus_config = value & priv->hw->mii.clk_csr_mask; +} + /** * stmmac_mdio_register * @ndev: net device structure @@ -537,6 +543,8 @@ int stmmac_mdio_register(struct net_device *ndev) if (!mdio_bus_data) return 0; + stmmac_mdio_bus_config(priv, priv->clk_csr); + new_bus = mdiobus_alloc(); if (!new_bus) return -ENOMEM; From 6cb3d67ad624de8c4ef2844386d7e37ccb9042b9 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:15 +0100 Subject: [PATCH 04/11] net: stmmac: mdio: move stmmac_mdio_format_addr() into read/write Move stmmac_mdio_format_addr() into stmmac_mdio_read() and stmmac_mdio_write(). Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8o7-00000001vom-1pN8@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 4294262c208d..d588475b4279 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -240,16 +240,20 @@ static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, MII_BUSY; } -static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) +static int stmmac_mdio_read(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, int data) { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; + u32 value; int ret; ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); if (ret) return ret; + value = stmmac_mdio_format_addr(priv, pa, gr) | cmd; + writel(data, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_address); @@ -275,17 +279,18 @@ static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); int data = 0; - u32 value; + u32 cmd; data = pm_runtime_resume_and_get(priv->device); if (data < 0) return data; - value = stmmac_mdio_format_addr(priv, phyaddr, phyreg); if (priv->plat->has_gmac4) - value |= MII_GMAC4_READ; + cmd = MII_GMAC4_READ; + else + cmd = 0; - data = stmmac_mdio_read(priv, data, value); + data = stmmac_mdio_read(priv, phyaddr, phyreg, cmd, data); pm_runtime_put(priv->device); @@ -308,29 +313,29 @@ static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, { struct stmmac_priv *priv = netdev_priv(bus->priv); int data = 0; - u32 value; + u32 cmd; data = pm_runtime_resume_and_get(priv->device); if (data < 0) return data; - value = stmmac_mdio_format_addr(priv, phyaddr, devad); - value |= MII_GMAC4_READ; - value |= MII_GMAC4_C45E; + cmd = MII_GMAC4_READ | MII_GMAC4_C45E; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; - data = stmmac_mdio_read(priv, data, value); + data = stmmac_mdio_read(priv, phyaddr, devad, cmd, data); pm_runtime_put(priv->device); return data; } -static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value) +static int stmmac_mdio_write(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, int data) { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; + u32 value; int ret; /* Wait until any existing MII operation is complete */ @@ -338,6 +343,8 @@ static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value) if (ret) return ret; + value = stmmac_mdio_format_addr(priv, pa, gr) | cmd; + /* Set the MII address register to write */ writel(data, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_address); @@ -359,19 +366,18 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, { struct stmmac_priv *priv = netdev_priv(bus->priv); int ret, data = phydata; - u32 value; + u32 cmd; ret = pm_runtime_resume_and_get(priv->device); if (ret < 0) return ret; - value = stmmac_mdio_format_addr(priv, phyaddr, phyreg); if (priv->plat->has_gmac4) - value |= MII_GMAC4_WRITE; + cmd = MII_GMAC4_WRITE; else - value |= MII_WRITE; + cmd = MII_WRITE; - ret = stmmac_mdio_write(priv, data, value); + ret = stmmac_mdio_write(priv, phyaddr, phyreg, cmd, data); pm_runtime_put(priv->device); @@ -392,19 +398,17 @@ static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr, { struct stmmac_priv *priv = netdev_priv(bus->priv); int ret, data = phydata; - u32 value; + u32 cmd; ret = pm_runtime_resume_and_get(priv->device); if (ret < 0) return ret; - value = stmmac_mdio_format_addr(priv, phyaddr, devad); - value |= MII_GMAC4_WRITE; - value |= MII_GMAC4_C45E; + cmd = MII_GMAC4_WRITE | MII_GMAC4_C45E; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; - ret = stmmac_mdio_write(priv, data, value); + ret = stmmac_mdio_write(priv, phyaddr, devad, cmd, data); pm_runtime_put(priv->device); From 9b0ed33a4256af56bcb89b575468a7c3b1e5c267 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:20 +0100 Subject: [PATCH 05/11] net: stmmac: mdio: merge stmmac_mdio_read() and stmmac_mdio_write() stmmac_mdio_read() and stmmac_mdio_write() are virtually identical except for the final read in the stmmac_mdio_read(). Handle this as a flag. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oC-00000001vos-2JnA@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index d588475b4279..4e2eb206a234 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -240,29 +240,41 @@ static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, MII_BUSY; } +static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, u32 data, bool read) +{ + void __iomem *mii_address = priv->ioaddr + priv->hw->mii.addr; + void __iomem *mii_data = priv->ioaddr + priv->hw->mii.data; + u32 addr; + int ret; + + ret = stmmac_mdio_wait(mii_address, MII_BUSY); + if (ret) + return ret; + + addr = stmmac_mdio_format_addr(priv, pa, gr) | cmd; + + writel(data, mii_data); + writel(addr, mii_address); + + ret = stmmac_mdio_wait(mii_address, MII_BUSY); + if (ret) + return ret; + + /* Read the data from the MII data register if in read mode */ + return read ? readl(mii_data) & MII_DATA_MASK : 0; +} + static int stmmac_mdio_read(struct stmmac_priv *priv, unsigned int pa, unsigned int gr, u32 cmd, int data) { - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; - u32 value; - int ret; + return stmmac_mdio_access(priv, pa, gr, cmd, data, true); +} - ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); - if (ret) - return ret; - - value = stmmac_mdio_format_addr(priv, pa, gr) | cmd; - - writel(data, priv->ioaddr + mii_data); - writel(value, priv->ioaddr + mii_address); - - ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); - if (ret) - return ret; - - /* Read the data from the MII data register */ - return readl(priv->ioaddr + mii_data) & MII_DATA_MASK; +static int stmmac_mdio_write(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, int data) +{ + return stmmac_mdio_access(priv, pa, gr, cmd, data, false); } /** @@ -330,29 +342,6 @@ static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, return data; } -static int stmmac_mdio_write(struct stmmac_priv *priv, unsigned int pa, - unsigned int gr, u32 cmd, int data) -{ - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; - u32 value; - int ret; - - /* Wait until any existing MII operation is complete */ - ret = stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); - if (ret) - return ret; - - value = stmmac_mdio_format_addr(priv, pa, gr) | cmd; - - /* Set the MII address register to write */ - writel(data, priv->ioaddr + mii_data); - writel(value, priv->ioaddr + mii_address); - - /* Wait until any existing MII operation is complete */ - return stmmac_mdio_wait(priv->ioaddr + mii_address, MII_BUSY); -} - /** * stmmac_mdio_write_c22 * @bus: points to the mii_bus structure From 9b88194a3b68ee8b818d917eac20e5e2f7803ecf Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:25 +0100 Subject: [PATCH 06/11] net: stmmac: mdio: move runtime PM into stmmac_mdio_access() Move the runtime PM handling into the common stmmac_mdio_access() function, rather than having it in the four top-level bus access functions. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oH-00000001voy-2jfU@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 71 ++++++------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 4e2eb206a234..c95e9799273f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -248,9 +248,13 @@ static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, u32 addr; int ret; + ret = pm_runtime_resume_and_get(priv->device); + if (ret < 0) + return ret; + ret = stmmac_mdio_wait(mii_address, MII_BUSY); if (ret) - return ret; + goto out; addr = stmmac_mdio_format_addr(priv, pa, gr) | cmd; @@ -259,10 +263,15 @@ static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, ret = stmmac_mdio_wait(mii_address, MII_BUSY); if (ret) - return ret; + goto out; /* Read the data from the MII data register if in read mode */ - return read ? readl(mii_data) & MII_DATA_MASK : 0; + ret = read ? readl(mii_data) & MII_DATA_MASK : 0; + +out: + pm_runtime_put(priv->device); + + return ret; } static int stmmac_mdio_read(struct stmmac_priv *priv, unsigned int pa, @@ -290,23 +299,14 @@ static int stmmac_mdio_write(struct stmmac_priv *priv, unsigned int pa, static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int data = 0; u32 cmd; - data = pm_runtime_resume_and_get(priv->device); - if (data < 0) - return data; - if (priv->plat->has_gmac4) cmd = MII_GMAC4_READ; else cmd = 0; - data = stmmac_mdio_read(priv, phyaddr, phyreg, cmd, data); - - pm_runtime_put(priv->device); - - return data; + return stmmac_mdio_read(priv, phyaddr, phyreg, cmd, 0); } /** @@ -324,22 +324,10 @@ static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int data = 0; - u32 cmd; + int data = phyreg << MII_GMAC4_REG_ADDR_SHIFT; + u32 cmd = MII_GMAC4_READ | MII_GMAC4_C45E; - data = pm_runtime_resume_and_get(priv->device); - if (data < 0) - return data; - - cmd = MII_GMAC4_READ | MII_GMAC4_C45E; - - data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; - - data = stmmac_mdio_read(priv, phyaddr, devad, cmd, data); - - pm_runtime_put(priv->device); - - return data; + return stmmac_mdio_read(priv, phyaddr, devad, cmd, data); } /** @@ -354,23 +342,14 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, u16 phydata) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int ret, data = phydata; u32 cmd; - ret = pm_runtime_resume_and_get(priv->device); - if (ret < 0) - return ret; - if (priv->plat->has_gmac4) cmd = MII_GMAC4_WRITE; else cmd = MII_WRITE; - ret = stmmac_mdio_write(priv, phyaddr, phyreg, cmd, data); - - pm_runtime_put(priv->device); - - return ret; + return stmmac_mdio_write(priv, phyaddr, phyreg, cmd, phydata); } /** @@ -386,22 +365,12 @@ static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr, int devad, int phyreg, u16 phydata) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int ret, data = phydata; - u32 cmd; - - ret = pm_runtime_resume_and_get(priv->device); - if (ret < 0) - return ret; - - cmd = MII_GMAC4_WRITE | MII_GMAC4_C45E; + u32 cmd = MII_GMAC4_WRITE | MII_GMAC4_C45E; + int data = phydata; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; - ret = stmmac_mdio_write(priv, phyaddr, devad, cmd, data); - - pm_runtime_put(priv->device); - - return ret; + return stmmac_mdio_write(priv, phyaddr, devad, cmd, data); } /** From 3581acbb789ac5539ff771f3af67f8cbc9223ea9 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:30 +0100 Subject: [PATCH 07/11] net: stmmac: mdio: improve mdio register field definitions Include the register name in the definitions, and use a name which more closely resembles that used in documentation, while still being descriptive. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oM-00000001vp4-3DC5@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index c95e9799273f..f2b4c1b70ef5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -23,9 +23,9 @@ #include "dwxgmac2.h" #include "stmmac.h" -#define MII_BUSY 0x00000001 -#define MII_WRITE 0x00000002 -#define MII_DATA_MASK GENMASK(15, 0) +#define MII_ADDR_GBUSY BIT(0) +#define MII_ADDR_GWRITE BIT(1) +#define MII_DATA_GD_MASK GENMASK(15, 0) /* GMAC4 defines */ #define MII_GMAC4_GOC_SHIFT 2 @@ -237,7 +237,7 @@ static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, return ((pa << mii_regs->addr_shift) & mii_regs->addr_mask) | ((gr << mii_regs->reg_shift) & mii_regs->reg_mask) | priv->gmii_address_bus_config | - MII_BUSY; + MII_ADDR_GBUSY; } static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, @@ -252,7 +252,7 @@ static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, if (ret < 0) return ret; - ret = stmmac_mdio_wait(mii_address, MII_BUSY); + ret = stmmac_mdio_wait(mii_address, MII_ADDR_GBUSY); if (ret) goto out; @@ -261,12 +261,12 @@ static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, writel(data, mii_data); writel(addr, mii_address); - ret = stmmac_mdio_wait(mii_address, MII_BUSY); + ret = stmmac_mdio_wait(mii_address, MII_ADDR_GBUSY); if (ret) goto out; /* Read the data from the MII data register if in read mode */ - ret = read ? readl(mii_data) & MII_DATA_MASK : 0; + ret = read ? readl(mii_data) & MII_DATA_GD_MASK : 0; out: pm_runtime_put(priv->device); @@ -347,7 +347,7 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, if (priv->plat->has_gmac4) cmd = MII_GMAC4_WRITE; else - cmd = MII_WRITE; + cmd = MII_ADDR_GWRITE; return stmmac_mdio_write(priv, phyaddr, phyreg, cmd, phydata); } From 661a868937a1cf73bd2de3688394ad2597960991 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:35 +0100 Subject: [PATCH 08/11] net: stmmac: mdio: move initialisation of priv->clk_csr to stmmac_mdio The only user of priv->clk_csr is the MDIO code, so move its initialisation to stmmac_mdio.c. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oR-00000001vpB-3fbY@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 82 ----------------- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 88 ++++++++++++++++++- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f0abd99fd137..419cb49ee5a2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -314,77 +314,6 @@ static void stmmac_global_err(struct stmmac_priv *priv) stmmac_service_event_schedule(priv); } -/** - * stmmac_clk_csr_set - dynamically set the MDC clock - * @priv: driver private structure - * Description: this is to dynamically set the MDC clock according to the csr - * clock input. - * Note: - * If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be - * changed at run-time and it is fixed (as reported in the driver - * documentation). Viceversa the driver will try to set the MDC - * clock dynamically according to the actual clock input. - */ -static void stmmac_clk_csr_set(struct stmmac_priv *priv) -{ - unsigned long clk_rate; - - clk_rate = clk_get_rate(priv->plat->stmmac_clk); - - /* Platform provided default clk_csr would be assumed valid - * for all other cases except for the below mentioned ones. - * For values higher than the IEEE 802.3 specified frequency - * we can not estimate the proper divider as it is not known - * the frequency of clk_csr_i. So we do not change the default - * divider. - */ - if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { - if (clk_rate < CSR_F_35M) - priv->clk_csr = STMMAC_CSR_20_35M; - else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) - priv->clk_csr = STMMAC_CSR_35_60M; - else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) - priv->clk_csr = STMMAC_CSR_60_100M; - else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) - priv->clk_csr = STMMAC_CSR_100_150M; - else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) - priv->clk_csr = STMMAC_CSR_150_250M; - else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) - priv->clk_csr = STMMAC_CSR_250_300M; - else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) - priv->clk_csr = STMMAC_CSR_300_500M; - else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) - priv->clk_csr = STMMAC_CSR_500_800M; - } - - if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { - if (clk_rate > 160000000) - priv->clk_csr = 0x03; - else if (clk_rate > 80000000) - priv->clk_csr = 0x02; - else if (clk_rate > 40000000) - priv->clk_csr = 0x01; - else - priv->clk_csr = 0; - } - - if (priv->plat->has_xgmac) { - if (clk_rate > 400000000) - priv->clk_csr = 0x5; - else if (clk_rate > 350000000) - priv->clk_csr = 0x4; - else if (clk_rate > 300000000) - priv->clk_csr = 0x3; - else if (clk_rate > 250000000) - priv->clk_csr = 0x2; - else if (clk_rate > 150000000) - priv->clk_csr = 0x1; - else - priv->clk_csr = 0x0; - } -} - static void print_pkt(unsigned char *buf, int len) { pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); @@ -7718,17 +7647,6 @@ int stmmac_dvr_probe(struct device *device, stmmac_fpe_init(priv); - /* If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be - * changed at run-time and it is fixed. Viceversa the driver'll try to - * set the MDC clock dynamically according to the csr actual - * clock input. - */ - if (priv->plat->clk_csr >= 0) - priv->clk_csr = priv->plat->clk_csr; - else - stmmac_clk_csr_set(priv); - stmmac_check_pcs_mode(priv); pm_runtime_get_noresume(device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index f2b4c1b70ef5..0b5282bf6d1e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -473,8 +473,92 @@ void stmmac_pcs_clean(struct net_device *ndev) priv->hw->xpcs = NULL; } -static void stmmac_mdio_bus_config(struct stmmac_priv *priv, u32 value) +/** + * stmmac_clk_csr_set - dynamically set the MDC clock + * @priv: driver private structure + * Description: this is to dynamically set the MDC clock according to the csr + * clock input. + * Note: + * If a specific clk_csr value is passed from the platform + * this means that the CSR Clock Range selection cannot be + * changed at run-time and it is fixed (as reported in the driver + * documentation). Viceversa the driver will try to set the MDC + * clock dynamically according to the actual clock input. + */ +static void stmmac_clk_csr_set(struct stmmac_priv *priv) { + unsigned long clk_rate; + + clk_rate = clk_get_rate(priv->plat->stmmac_clk); + + /* Platform provided default clk_csr would be assumed valid + * for all other cases except for the below mentioned ones. + * For values higher than the IEEE 802.3 specified frequency + * we can not estimate the proper divider as it is not known + * the frequency of clk_csr_i. So we do not change the default + * divider. + */ + if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { + if (clk_rate < CSR_F_35M) + priv->clk_csr = STMMAC_CSR_20_35M; + else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) + priv->clk_csr = STMMAC_CSR_35_60M; + else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) + priv->clk_csr = STMMAC_CSR_60_100M; + else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) + priv->clk_csr = STMMAC_CSR_100_150M; + else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) + priv->clk_csr = STMMAC_CSR_150_250M; + else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) + priv->clk_csr = STMMAC_CSR_250_300M; + else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) + priv->clk_csr = STMMAC_CSR_300_500M; + else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) + priv->clk_csr = STMMAC_CSR_500_800M; + } + + if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { + if (clk_rate > 160000000) + priv->clk_csr = 0x03; + else if (clk_rate > 80000000) + priv->clk_csr = 0x02; + else if (clk_rate > 40000000) + priv->clk_csr = 0x01; + else + priv->clk_csr = 0; + } + + if (priv->plat->has_xgmac) { + if (clk_rate > 400000000) + priv->clk_csr = 0x5; + else if (clk_rate > 350000000) + priv->clk_csr = 0x4; + else if (clk_rate > 300000000) + priv->clk_csr = 0x3; + else if (clk_rate > 250000000) + priv->clk_csr = 0x2; + else if (clk_rate > 150000000) + priv->clk_csr = 0x1; + else + priv->clk_csr = 0x0; + } +} + +static void stmmac_mdio_bus_config(struct stmmac_priv *priv) +{ + u32 value; + + /* If a specific clk_csr value is passed from the platform, this means + * that the CSR Clock Range value should not be computed from the CSR + * clock. + */ + if (priv->plat->clk_csr >= 0) { + value = priv->plat->clk_csr; + } else { + stmmac_clk_csr_set(priv); + value = priv->clk_csr; + } + value <<= priv->hw->mii.clk_csr_shift; if (value & ~priv->hw->mii.clk_csr_mask) @@ -505,7 +589,7 @@ int stmmac_mdio_register(struct net_device *ndev) if (!mdio_bus_data) return 0; - stmmac_mdio_bus_config(priv, priv->clk_csr); + stmmac_mdio_bus_config(priv); new_bus = mdiobus_alloc(); if (!new_bus) From 231e2b016fb24ba77009811e2feaf2d2ebe0639b Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:40 +0100 Subject: [PATCH 09/11] net: stmmac: mdio: return clk_csr value from stmmac_clk_csr_set() Return the clk_csr value from stmmac_clk_csr_set() rather than using priv->clk_csr, as this struct member now serves very little purpose. This allows us to remove priv->clk_csr. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oW-00000001vpH-46zf@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 68 +++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 4d5577935b13..ec6bccb13710 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -289,7 +289,6 @@ struct stmmac_priv { u32 msg_enable; int wolopts; int wol_irq; - int clk_csr; u32 gmii_address_bus_config; struct timer_list eee_ctrl_timer; int lpi_irq; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 0b5282bf6d1e..e5ca206ee46f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -478,6 +478,7 @@ void stmmac_pcs_clean(struct net_device *ndev) * @priv: driver private structure * Description: this is to dynamically set the MDC clock according to the csr * clock input. + * Return: MII register CR field value * Note: * If a specific clk_csr value is passed from the platform * this means that the CSR Clock Range selection cannot be @@ -485,9 +486,10 @@ void stmmac_pcs_clean(struct net_device *ndev) * documentation). Viceversa the driver will try to set the MDC * clock dynamically according to the actual clock input. */ -static void stmmac_clk_csr_set(struct stmmac_priv *priv) +static u32 stmmac_clk_csr_set(struct stmmac_priv *priv) { unsigned long clk_rate; + u32 value = ~0; clk_rate = clk_get_rate(priv->plat->stmmac_clk); @@ -498,50 +500,50 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv) * the frequency of clk_csr_i. So we do not change the default * divider. */ - if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { - if (clk_rate < CSR_F_35M) - priv->clk_csr = STMMAC_CSR_20_35M; - else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) - priv->clk_csr = STMMAC_CSR_35_60M; - else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) - priv->clk_csr = STMMAC_CSR_60_100M; - else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) - priv->clk_csr = STMMAC_CSR_100_150M; - else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) - priv->clk_csr = STMMAC_CSR_150_250M; - else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) - priv->clk_csr = STMMAC_CSR_250_300M; - else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) - priv->clk_csr = STMMAC_CSR_300_500M; - else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) - priv->clk_csr = STMMAC_CSR_500_800M; - } + if (clk_rate < CSR_F_35M) + value = STMMAC_CSR_20_35M; + else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) + value = STMMAC_CSR_35_60M; + else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) + value = STMMAC_CSR_60_100M; + else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) + value = STMMAC_CSR_100_150M; + else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) + value = STMMAC_CSR_150_250M; + else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) + value = STMMAC_CSR_250_300M; + else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) + value = STMMAC_CSR_300_500M; + else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) + value = STMMAC_CSR_500_800M; if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { if (clk_rate > 160000000) - priv->clk_csr = 0x03; + value = 0x03; else if (clk_rate > 80000000) - priv->clk_csr = 0x02; + value = 0x02; else if (clk_rate > 40000000) - priv->clk_csr = 0x01; + value = 0x01; else - priv->clk_csr = 0; + value = 0; } if (priv->plat->has_xgmac) { if (clk_rate > 400000000) - priv->clk_csr = 0x5; + value = 0x5; else if (clk_rate > 350000000) - priv->clk_csr = 0x4; + value = 0x4; else if (clk_rate > 300000000) - priv->clk_csr = 0x3; + value = 0x3; else if (clk_rate > 250000000) - priv->clk_csr = 0x2; + value = 0x2; else if (clk_rate > 150000000) - priv->clk_csr = 0x1; + value = 0x1; else - priv->clk_csr = 0x0; + value = 0x0; } + + return value; } static void stmmac_mdio_bus_config(struct stmmac_priv *priv) @@ -552,12 +554,10 @@ static void stmmac_mdio_bus_config(struct stmmac_priv *priv) * that the CSR Clock Range value should not be computed from the CSR * clock. */ - if (priv->plat->clk_csr >= 0) { + if (priv->plat->clk_csr >= 0) value = priv->plat->clk_csr; - } else { - stmmac_clk_csr_set(priv); - value = priv->clk_csr; - } + else + value = stmmac_clk_csr_set(priv); value <<= priv->hw->mii.clk_csr_shift; From 78c91bec8fb977cd509e873f9ef6cb74cfdcbe57 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:46 +0100 Subject: [PATCH 10/11] net: stmmac: mdio: remove redundant clock rate tests The pattern: ... if (v < A) ... else if (v >= A && v < B) ... can be simplified to: ... if (v < A) ... else if (v < B) ... which makes the string of ifelse more readable. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oc-00000001vpN-0S1A@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index e5ca206ee46f..f408737f6fc7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -502,19 +502,19 @@ static u32 stmmac_clk_csr_set(struct stmmac_priv *priv) */ if (clk_rate < CSR_F_35M) value = STMMAC_CSR_20_35M; - else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) + else if (clk_rate < CSR_F_60M) value = STMMAC_CSR_35_60M; - else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) + else if (clk_rate < CSR_F_100M) value = STMMAC_CSR_60_100M; - else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) + else if (clk_rate < CSR_F_150M) value = STMMAC_CSR_100_150M; - else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) + else if (clk_rate < CSR_F_250M) value = STMMAC_CSR_150_250M; - else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) + else if (clk_rate <= CSR_F_300M) value = STMMAC_CSR_250_300M; - else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) + else if (clk_rate < CSR_F_500M) value = STMMAC_CSR_300_500M; - else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) + else if (clk_rate < CSR_F_800M) value = STMMAC_CSR_500_800M; if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { From fc8f62c827ead74ec6bdf76bc78993e9402968ee Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 4 Sep 2025 13:11:51 +0100 Subject: [PATCH 11/11] net: stmmac: use STMMAC_CSR_xxx definitions in platform glue Use the STMMAC_CSR_xxx definitions to initialise plat->clk_csr in the platform glue drivers to make the integer values meaningful. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Tested-by: Mohd Ayaan Anwar Link: https://patch.msgid.link/E1uu8oh-00000001vpT-0vk2@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 5 +++-- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 3ff271b097ea..e74d00984b88 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -563,7 +563,8 @@ static int intel_mac_finish(struct net_device *ndev, static void common_default_data(struct plat_stmmacenet_data *plat) { - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -610,7 +611,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->pdev = pdev; plat->phy_addr = -1; - plat->clk_csr = 5; + plat->clk_csr = STMMAC_CSR_250_300M; plat->has_gmac = 0; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 6fca0fca4892..dd82dc2189e9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -90,7 +90,8 @@ static void loongson_default_data(struct pci_dev *pdev, /* Get bus_id, this can be overwritten later */ plat->bus_id = pci_dev_id(pdev); - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index e6a7d0ddac2a..4e3aa611fda8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -21,7 +21,8 @@ struct stmmac_pci_info { static void common_default_data(struct plat_stmmacenet_data *plat) { - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -74,7 +75,7 @@ static int snps_gmac5_default_data(struct pci_dev *pdev, { int i; - plat->clk_csr = 5; + plat->clk_csr = STMMAC_CSR_250_300M; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 1; plat->flags |= STMMAC_FLAG_TSO_EN;