Thread (16 messages) 16 messages, 6 authors, 1d ago

RE: [net-next,PATCH 2/2] enetc: Make eMDIO MDC rate configurable from DT

flat view

From: Wei Fang <wei.fang@nxp.com>
Date: 2026-10-17 02:24:56
Also in: imx, linux-arm-kernel, linux-devicetree, linuxppc-dev, lkml

On Fri, Oct 16, 2026 at 09:32:01PM +0200, Marek Vasut wrote:
quoted
The current eMDIO MDC rate is hard-coded in the drivers which use the
eMDIO MDC, this is not flexible for various deployments of SoCs which
use the eMDIO interface, for example i.MX95 B0 MDC clock is currently
set to 644 kHz.

Introduce enetc_mdio_priv .mdc_div field which contains the divider
used for MDC clock and pass it around, including into functions which
configure the MDC clock. This way, drivers which use the eMDIO can set
the divider as needed. Introduce enetc_mdio_update_mdc_div() function
which calculates the divider from upstream clock and clock-frequency
DT property, both of which are optional to retain compatibility with
older DTs. This is modeled according to xgmac_mdio_set_mdc_freq().

Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: "Christophe Leroy (CS GROUP)" <chleroy@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: Clark Wang <xiaoning.wang@nxp.com>
Cc: Claudiu Manoil <claudiu.manoil@nxp.com>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Eric Dumazet <edumazet@kernel.org>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Rob Herring <robh@kernel.org>
Cc: UNGLinuxDriver@microchip.com
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
Cc: Wei Fang <wei.fang@nxp.com>
Cc: devicetree@vger.kernel.org
Cc: imx@lists.linux.dev
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: netdev@vger.kernel.org
---
NOTE: I could only test i.MX95 , I could not test LS or Felix
---
 drivers/net/dsa/ocelot/felix_vsc9959.c        |  5 +++
 .../net/ethernet/freescale/enetc/enetc_mdio.c | 39 ++++++++++++++++---
 .../ethernet/freescale/enetc/enetc_pci_mdio.c |  5 +++
 .../freescale/enetc/enetc_pf_common.c         | 10 +++++
 include/linux/fsl/enetc_mdio.h                |  6 +++
 5 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c
b/drivers/net/dsa/ocelot/felix_vsc9959.c
quoted
index 8387dd208adb9..dbeec1b229325 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1008,8 +1008,13 @@ static int vsc9959_mdio_bus_alloc(struct ocelot
*ocelot)
quoted
 	 * starting with the proper offset.
 	 */
 	mdio_priv->mdio_base = 0;
+	mdio_priv->mdc_div = ENETC_MDIO_DEFAULT_DIVIDER;
 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));

+	rc = enetc_mdio_update_mdc_div(bus);
+	if (rc)
+		return rc;
+
 	/* Needed in order to initialize the bus mutex lock */
 	rc = mdiobus_register(bus);
 	if (rc < 0) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
quoted
index 998aaa394e9c4..93d61c2f1464f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /* Copyright 2019 NXP */

+#include <linux/clk.h>
 #include <linux/fsl/enetc_mdio.h>
 #include <linux/mdio.h>
 #include <linux/of_mdio.h>
@@ -22,9 +23,9 @@
  /* external MDIO only - driven on neg MDC edge */
 #define MDIO_CFG_NEG		BIT(23)

-#define ENETC_EMDIO_CFG \
+#define ENETC_EMDIO_CFG(mdc_div) \
 	(MDIO_CFG_HOLD(2) | \
-	 MDIO_CFG_CLKDIV(258) | \
+	 MDIO_CFG_CLKDIV(mdc_div) | \
 	 MDIO_CFG_NEG)

 #define MDIO_CTL_DEV_ADDR(x)	((x) & 0x1f)
@@ -63,7 +64,7 @@ int enetc_mdio_write_c22(struct mii_bus *bus, int
phy_id, int regnum,
quoted
 	u16 dev_addr;
 	int ret;

-	mdio_cfg = ENETC_EMDIO_CFG;
+	mdio_cfg = ENETC_EMDIO_CFG(mdio_priv->mdc_div);
 	dev_addr = regnum & 0x1f;
 	mdio_cfg &= ~MDIO_CFG_ENC45;
@@ -95,7 +96,7 @@ int enetc_mdio_write_c45(struct mii_bus *bus, int
phy_id, int dev_addr,
quoted
 	u32 mdio_ctl, mdio_cfg;
 	int ret;

-	mdio_cfg = ENETC_EMDIO_CFG;
+	mdio_cfg = ENETC_EMDIO_CFG(mdio_priv->mdc_div);
 	mdio_cfg |= MDIO_CFG_ENC45;

 	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
@@ -133,7 +134,7 @@ int enetc_mdio_read_c22(struct mii_bus *bus, int
phy_id, int regnum)
quoted
 	u16 dev_addr, value;
 	int ret;

-	mdio_cfg = ENETC_EMDIO_CFG;
+	mdio_cfg = ENETC_EMDIO_CFG(mdio_priv->mdc_div);
 	dev_addr = regnum & 0x1f;
 	mdio_cfg &= ~MDIO_CFG_ENC45;
@@ -176,7 +177,7 @@ int enetc_mdio_read_c45(struct mii_bus *bus, int
phy_id, int dev_addr,
quoted
 	u16 value;
 	int ret;

-	mdio_cfg = ENETC_EMDIO_CFG;
+	mdio_cfg = ENETC_EMDIO_CFG(mdio_priv->mdc_div);
 	mdio_cfg |= MDIO_CFG_ENC45;

 	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
@@ -231,6 +232,32 @@ struct enetc_hw *enetc_hw_alloc(struct device
*dev, void __iomem *port_regs)
quoted
 }
 EXPORT_SYMBOL_GPL(enetc_hw_alloc);

+int enetc_mdio_update_mdc_div(struct mii_bus *bus)
+{
+	struct enetc_mdio_priv *mdio_priv = bus->priv;
+	struct device *dev = bus->parent;
+	struct clk *enet_clk;
+	u32 div, mdc_freq;
+
+	if (device_property_read_u32(dev, "clock-frequency", &mdc_freq))
+		return 0;
+
+	enet_clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(enet_clk))
+		return dev_err_probe(dev, PTR_ERR(enet_clk),
+				     "Input clock unknown, not changing MDC
frequency\n");

binding said clock is optional. If return failure here, it will block
existing dts, which have not clock property.
For EMDIO device, the clocks property is not added to
fsl,enetc-mdio.yaml, I suppose this property should be added to the
dt-binding doc if the clock is really needed here.

For ENETC device, we already have a 'ref' clock in the enetc node,
so devm_clk_get(dev, NULL) may get the 'ref' clock rather than the
system clock of NETC.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help