[U-Boot] [PATCH v5 1/3] net: phy: Add generic helpers to access MMD PHY registers

Joe Hershberger joe.hershberger at ni.com
Tue Feb 19 18:14:07 UTC 2019


On Fri, Feb 8, 2019 at 11:29 AM Carlo Caione <ccaione at baylibre.com> wrote:
>
> Two new helper functions (phy_read_mmd() and phy_write_mmd()) are added
> to allow access to the MMD PHY registers.
>
> The MMD PHY registers can be accessed by several means:
>
> 1. Using two new MMD access function hooks in the PHY driver. These
> functions can be implemented when the PHY driver does not support the
> standard IEEE Compatible clause 45 access mechanism described in clause
> 22 or if the PHY uses its own non-standard access mechanism.
>
> 2. Direct access for C45 PHYs and C22 PHYs when accessing the reachable
> DEVADs.
>
> 3. The standard clause 45 access extensions to the MMD registers through
> the indirection registers (clause 22) in all the other cases.
>
> Signed-off-by: Carlo Caione <ccaione at baylibre.com>

Except for the off-by-ones below...
Acked-by: Joe Hershberger <joe.hershberger at ni.com>

> ---
>  drivers/net/phy/phy.c |  4 +++
>  include/phy.h         | 70 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 74 insertions(+)
>
> diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
> index cda4caa803..6769047407 100644
> --- a/drivers/net/phy/phy.c
> +++ b/drivers/net/phy/phy.c
> @@ -549,6 +549,10 @@ int phy_register(struct phy_driver *drv)
>                 drv->readext += gd->reloc_off;
>         if (drv->writeext)
>                 drv->writeext += gd->reloc_off;
> +       if (drv->read_mmd)
> +               drv->read_mmd += gd->reloc_off;
> +       if (drv->write_mmd)
> +               drv->write_mmd += gd->reloc_off;
>  #endif
>         return 0;
>  }
> diff --git a/include/phy.h b/include/phy.h
> index b86fdfb2ce..7ec2b4e86c 100644
> --- a/include/phy.h
> +++ b/include/phy.h
> @@ -101,6 +101,14 @@ struct phy_driver {
>         int (*readext)(struct phy_device *phydev, int addr, int devad, int reg);
>         int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg,
>                         u16 val);
> +
> +       /* Phy specific driver override for reading a MMD register */
> +       int (*read_mmd)(struct phy_device *phydev, int devad, int reg);
> +
> +       /* Phy specific driver override for writing a MMD register */
> +       int (*write_mmd)(struct phy_device *phydev, int devad, int reg,
> +                        u16 val);
> +
>         struct list_head list;
>  };
>
> @@ -164,6 +172,68 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum,
>         return bus->write(bus, phydev->addr, devad, regnum, val);
>  }
>
> +static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad,
> +                                         int regnum)
> +{
> +       /* Write the desired MMD Devad */
> +       phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
> +
> +       /* Write the desired MMD register address */
> +       phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
> +
> +       /* Select the Function : DATA with no post increment */
> +       phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
> +                 (devad | MII_MMD_CTRL_NOINCR));
> +}
> +
> +static inline int phy_read_mmd(struct phy_device *phydev, int devad,
> +                              int regnum)
> +{
> +       struct phy_driver *drv = phydev->drv;
> +
> +       if (regnum > (u16)~0 || devad > 32)

Shouldn't this be >= 32?

> +               return -EINVAL;
> +
> +       /* driver-specific access */
> +       if (drv->read_mmd)
> +               return drv->read_mmd(phydev, devad, regnum);
> +
> +       /* direct C45 / C22 access */
> +       if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
> +           devad == MDIO_DEVAD_NONE || !devad)
> +               return phy_read(phydev, devad, regnum);
> +
> +       /* indirect C22 access */
> +       phy_mmd_start_indirect(phydev, devad, regnum);
> +
> +       /* Read the content of the MMD's selected register */
> +       return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
> +}
> +
> +static inline int phy_write_mmd(struct phy_device *phydev, int devad,
> +                               int regnum, u16 val)
> +{
> +       struct phy_driver *drv = phydev->drv;
> +
> +       if (regnum > (u16)~0 || devad > 32)

Same here.

> +               return -EINVAL;
> +
> +       /* driver-specific access */
> +       if (drv->write_mmd)
> +               return drv->write_mmd(phydev, devad, regnum, val);
> +
> +       /* direct C45 / C22 access */
> +       if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
> +           devad == MDIO_DEVAD_NONE || !devad)
> +               return phy_write(phydev, devad, regnum, val);
> +
> +       /* indirect C22 access */
> +       phy_mmd_start_indirect(phydev, devad, regnum);
> +
> +       /* Write the data into MMD's selected register */
> +       return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
> +}
> +
>  #ifdef CONFIG_PHYLIB_10G
>  extern struct phy_driver gen10g_driver;
>
> --
> 2.19.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot


More information about the U-Boot mailing list