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 <[email protected]>
> Signed-off-by: Marek Vasut <[email protected]>
> ---
> Cc: "Christophe Leroy (CS GROUP)" <[email protected]>
> Cc: "David S. Miller" <[email protected]>
> Cc: Andrew Lunn <[email protected]>
> Cc: Clark Wang <[email protected]>
> Cc: Claudiu Manoil <[email protected]>
> Cc: Conor Dooley <[email protected]>
> Cc: Eric Dumazet <[email protected]>
> Cc: Frank Li <[email protected]>
> Cc: Jakub Kicinski <[email protected]>
> Cc: Krzysztof Kozlowski <[email protected]>
> Cc: Paolo Abeni <[email protected]>
> Cc: Rob Herring <[email protected]>
> Cc: [email protected]
> Cc: Vladimir Oltean <[email protected]>
> Cc: Wei Fang <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
> 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.

should be devm_clk_get_optional()?

Frank

Reply via email to