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

From: Wei Fang

Date: Fri Oct 16 2026 - 22:25:17 EST


> On Fri, Oct 16, 2026 at 09:32:01PM +0200, Marek Vasut wrote:
> > 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@xxxxxxx>
> > Signed-off-by: Marek Vasut <marex@xxxxxxxxxxxx>
> > ---
> > Cc: "Christophe Leroy (CS GROUP)" <chleroy@xxxxxxxxxx>
> > Cc: "David S. Miller" <davem@xxxxxxxxxxxxx>
> > Cc: Andrew Lunn <andrew+netdev@xxxxxxx>
> > Cc: Clark Wang <xiaoning.wang@xxxxxxx>
> > Cc: Claudiu Manoil <claudiu.manoil@xxxxxxx>
> > Cc: Conor Dooley <conor+dt@xxxxxxxxxx>
> > Cc: Eric Dumazet <edumazet@xxxxxxxxxx>
> > Cc: Frank Li <Frank.Li@xxxxxxx>
> > Cc: Jakub Kicinski <kuba@xxxxxxxxxx>
> > Cc: Krzysztof Kozlowski <krzk+dt@xxxxxxxxxx>
> > Cc: Paolo Abeni <pabeni@xxxxxxxxxx>
> > Cc: Rob Herring <robh@xxxxxxxxxx>
> > Cc: UNGLinuxDriver@xxxxxxxxxxxxx
> > Cc: Vladimir Oltean <vladimir.oltean@xxxxxxx>
> > Cc: Wei Fang <wei.fang@xxxxxxx>
> > Cc: devicetree@xxxxxxxxxxxxxxx
> > Cc: imx@xxxxxxxxxxxxxxx
> > Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
> > Cc: linux-kernel@xxxxxxxxxxxxxxx
> > Cc: linuxppc-dev@xxxxxxxxxxxxxxxx
> > Cc: netdev@xxxxxxxxxxxxxxx
> > ---
> > 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
> > 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)
> > * 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
> > 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,
> > 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,
> > 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)
> > 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,
> > 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)
> > }
> > 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.