[PATCH 3/3] net: ftmac100: add mii read and write callbacks

Ramon Fried rfried.dev at gmail.com
Tue Jan 10 18:13:12 CET 2023


On Wed, Dec 28, 2022 at 1:55 PM Sergei Antonov <saproj at gmail.com> wrote:
>
> Register mii_bus with read and write callbacks tp allow the 'mii'
> command to work. Use a timeout of 10 ms to wait for the R/W
> operations to complete.
>
> Signed-off-by: Sergei Antonov <saproj at gmail.com>
> ---
>  drivers/net/ftmac100.c | 103 +++++++++++++++++++++++++++++++++++++++++
>  drivers/net/ftmac100.h |   9 ++++
>  2 files changed, 112 insertions(+)
>
> diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
> index bb39e837bbe7..10395c94f9d1 100644
> --- a/drivers/net/ftmac100.c
> +++ b/drivers/net/ftmac100.c
> @@ -12,9 +12,13 @@
>  #include <env.h>
>  #include <malloc.h>
>  #include <net.h>
> +#include <phy.h>
> +#include <miiphy.h>
> +#include <dm/device_compat.h>
>  #include <asm/global_data.h>
>  #include <linux/delay.h>
>  #include <linux/io.h>
> +#include <linux/iopoll.h>
>
>  #include "ftmac100.h"
>  #ifdef CONFIG_DM_ETH
> @@ -23,12 +27,16 @@ DECLARE_GLOBAL_DATA_PTR;
>  #endif
>  #define ETH_ZLEN       60
>
> +/* Timeout for a mdio read/write operation */
> +#define FTMAC100_MDIO_TIMEOUT_USEC     10000
> +
>  struct ftmac100_data {
>         struct ftmac100_txdes txdes[1];
>         struct ftmac100_rxdes rxdes[PKTBUFSRX];
>         int rx_index;
>         const char *name;
>         struct ftmac100 *ftmac100;
> +       struct mii_dev *bus;
>  };
>
>  /*
> @@ -408,10 +416,104 @@ static int ftmac100_of_to_plat(struct udevice *dev)
>         return 0;
>  }
>
> +/*
> + * struct mii_bus functions
> + */
> +static int ftmac100_mdio_read(struct mii_dev *bus, int addr, int devad,
> +                             int reg)
> +{
> +       struct ftmac100_data *priv = bus->priv;
> +       struct ftmac100 *ftmac100 = priv->ftmac100;
> +       int phycr = FTMAC100_PHYCR_PHYAD(addr) |
> +                   FTMAC100_PHYCR_REGAD(reg) |
> +                   FTMAC100_PHYCR_MIIRD;
> +       int ret;
> +
> +       writel(phycr, &ftmac100->phycr);
> +
> +       ret = readl_poll_timeout(&ftmac100->phycr, phycr,
> +                                !(phycr & FTMAC100_PHYCR_MIIRD),
> +                                FTMAC100_MDIO_TIMEOUT_USEC);
> +       if (ret)
> +               pr_err("%s: mdio read failed (addr=0x%x reg=0x%x)\n",
> +                      bus->name, addr, reg);
> +       else
> +               ret = phycr & FTMAC100_PHYCR_MIIRDATA;
> +
> +       return ret;
> +}
> +
> +static int ftmac100_mdio_write(struct mii_dev *bus, int addr, int devad,
> +                              int reg, u16 value)
> +{
> +       struct ftmac100_data *priv = bus->priv;
> +       struct ftmac100 *ftmac100 = priv->ftmac100;
> +       int phycr = FTMAC100_PHYCR_PHYAD(addr) |
> +                   FTMAC100_PHYCR_REGAD(reg) |
> +                   FTMAC100_PHYCR_MIIWR;
> +       int ret;
> +
> +       writel(value, &ftmac100->phywdata);
> +       writel(phycr, &ftmac100->phycr);
> +
> +       ret = readl_poll_timeout(&ftmac100->phycr, phycr,
> +                                !(phycr & FTMAC100_PHYCR_MIIWR),
> +                                FTMAC100_MDIO_TIMEOUT_USEC);
> +       if (ret)
> +               pr_err("%s: mdio write failed (addr=0x%x reg=0x%x)\n",
> +                      bus->name, addr, reg);
> +
> +       return ret;
> +}
> +
> +static int ftmac100_mdio_init(struct udevice *dev)
> +{
> +       struct ftmac100_data *priv = dev_get_priv(dev);
> +       struct mii_dev *bus;
> +       int ret;
> +
> +       bus = mdio_alloc();
> +       if (!bus)
> +               return -ENOMEM;
> +
> +       bus->read  = ftmac100_mdio_read;
> +       bus->write = ftmac100_mdio_write;
> +       bus->priv  = priv;
> +
> +       ret = mdio_register_seq(bus, dev_seq(dev));
> +       if (ret) {
> +               mdio_free(bus);
> +               return ret;
> +       }
> +
> +       priv->bus = bus;
> +
> +       return 0;
> +}
> +
>  static int ftmac100_probe(struct udevice *dev)
>  {
>         struct ftmac100_data *priv = dev_get_priv(dev);
>         priv->name = dev->name;
> +       int ret = 0;
> +
> +       ret = ftmac100_mdio_init(dev);
> +       if (ret) {
> +               dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
> +               goto out;
> +       }
> +
> +out:
> +       return ret;
> +}
> +
> +static int ftmac100_remove(struct udevice *dev)
> +{
> +       struct ftmac100_data *priv = dev_get_priv(dev);
> +
> +       mdio_unregister(priv->bus);
> +       mdio_free(priv->bus);
> +
>         return 0;
>  }
>
> @@ -440,6 +542,7 @@ U_BOOT_DRIVER(ftmac100) = {
>         .bind   = ftmac100_bind,
>         .of_to_plat = ftmac100_of_to_plat,
>         .probe  = ftmac100_probe,
> +       .remove = ftmac100_remove,
>         .ops    = &ftmac100_ops,
>         .priv_auto      = sizeof(struct ftmac100_data),
>         .plat_auto      = sizeof(struct eth_pdata),
> diff --git a/drivers/net/ftmac100.h b/drivers/net/ftmac100.h
> index 75a49f628a69..21d339f835bf 100644
> --- a/drivers/net/ftmac100.h
> +++ b/drivers/net/ftmac100.h
> @@ -92,6 +92,15 @@ struct ftmac100 {
>  #define FTMAC100_MACCR_RX_MULTIPKT     (1 << 16)
>  #define FTMAC100_MACCR_RX_BROADPKT     (1 << 17)
>
> +/*
> + * PHY control register
> + */
> +#define FTMAC100_PHYCR_MIIRDATA                0xffff
> +#define FTMAC100_PHYCR_PHYAD(x)                (((x) & 0x1f) << 16)
> +#define FTMAC100_PHYCR_REGAD(x)                (((x) & 0x1f) << 21)
> +#define FTMAC100_PHYCR_MIIWR           BIT(27)
> +#define FTMAC100_PHYCR_MIIRD           BIT(26)
> +
>  /*
>   * Transmit descriptor, aligned to 16 bytes
>   */
> --
> 2.34.1
>
Reviewed-by: Ramon Fried <rfried.dev at gmail.com>


More information about the U-Boot mailing list