[U-Boot] [RFC PATCH] net: gem: Add support for more PHYs on MDIO bus

Joe Hershberger joe.hershberger at ni.com
Fri Feb 2 19:35:30 UTC 2018


Hi Michal,

On Thu, Feb 1, 2018 at 6:42 AM, Michal Simek <michal.simek at xilinx.com> wrote:
> Find out MDIO bus and enable MDIO access to it if this is done via
> different controller.
>
> Signed-off-by: Michal Simek <michal.simek at xilinx.com>
> ---
>
> Hi Joe,
>
> this is the code I have hacked a year ago for ZynqMP where we can have
> configuration that 4 gems are enabled but they share the same MDIO bus
> which can be assigned to only gem. Normally recommendation is that you
> should assign it to IP which is required for boot and this is suitable I
> would say for almost everybody.
> But for testing purpose it will be good to support sharing mdio bus
> between others IPs. This hack is "enabling" this for others gem but not
> across different ethernet drivers.

Seems practical.

> And my question is if there is any solution which can be used now for
> handling it. Or even this should work even now but we do something
> wrong.

I would envision some DM way to model the NIC, the MDIO bus, and the
PHY separately. The big roadblock is that the DTS format is different
for every NIC.

> I am refreshing this topic based on communication with Tomasz
> Gorochowik when he wanted to separate mdio part but it is not compatible
> with solution used in Linux which is pattern we should follow.

We do the same thing on our 7020 products.

> Note: I tested it only on zcu102 with the standard configuration but
> Tomasz confirmed that this is still working with shared mdio bus.
>
> Thanks,
> Michal
>
> ---
>  drivers/net/zynq_gem.c | 37 ++++++++++++++++++++++++++++++-------
>  1 file changed, 30 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
> index 2cc49bca922a..33245ec36e67 100644
> --- a/drivers/net/zynq_gem.c
> +++ b/drivers/net/zynq_gem.c
> @@ -177,6 +177,7 @@ struct zynq_gem_priv {
>         int phyaddr;
>         int init;
>         struct zynq_gem_regs *iobase;
> +       struct zynq_gem_regs *mdiobase;
>         phy_interface_t interface;
>         struct phy_device *phydev;
>         int phy_of_handle;
> @@ -189,7 +190,7 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
>                         u32 op, u16 *data)
>  {
>         u32 mgtcr;
> -       struct zynq_gem_regs *regs = priv->iobase;
> +       struct zynq_gem_regs *regs = priv->mdiobase;
>         int err;
>
>         err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
> @@ -314,7 +315,7 @@ static int zynq_phy_init(struct udevice *dev)
>  {
>         int ret;
>         struct zynq_gem_priv *priv = dev_get_priv(dev);
> -       struct zynq_gem_regs *regs = priv->iobase;
> +       struct zynq_gem_regs *regs_mdio = priv->mdiobase;
>         const u32 supported = SUPPORTED_10baseT_Half |
>                         SUPPORTED_10baseT_Full |
>                         SUPPORTED_100baseT_Half |
> @@ -323,7 +324,7 @@ static int zynq_phy_init(struct udevice *dev)
>                         SUPPORTED_1000baseT_Full;
>
>         /* Enable only MDIO bus */
> -       writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, &regs->nwctrl);
> +       writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, &regs_mdio->nwctrl);
>
>         if (priv->interface != PHY_INTERFACE_MODE_SGMII) {
>                 ret = phy_detection(dev);
> @@ -355,6 +356,7 @@ static int zynq_gem_init(struct udevice *dev)
>         unsigned long clk_rate = 0;
>         struct zynq_gem_priv *priv = dev_get_priv(dev);
>         struct zynq_gem_regs *regs = priv->iobase;
> +       struct zynq_gem_regs *regs_mdio = priv->mdiobase;
>         struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
>         struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2];
>
> @@ -397,7 +399,7 @@ static int zynq_gem_init(struct udevice *dev)
>                 writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);
>
>                 /* Setup for Network Control register, MDIO, Rx and Tx enable */
> -               setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
> +               setbits_le32(&regs_mdio->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
>
>                 /* Disable the second priority queue */
>                 dummy_tx_bd->addr = 0;
> @@ -623,6 +625,7 @@ static int zynq_gem_probe(struct udevice *dev)
>         void *bd_space;
>         struct zynq_gem_priv *priv = dev_get_priv(dev);
>         int ret;
> +       char name[MDIO_NAME_LEN];
>
>         /* Align rxbuffers to ARCH_DMA_MINALIGN */
>         priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN);
> @@ -648,6 +651,9 @@ static int zynq_gem_probe(struct udevice *dev)
>         priv->bus->write = zynq_gem_miiphy_write;
>         priv->bus->priv = priv;
>
> +       snprintf(name, MDIO_NAME_LEN, "gem%lx", (ulong)priv->iobase);
> +       strncpy(priv->bus->name, name, MDIO_NAME_LEN);
> +
>         ret = mdio_register_seq(priv->bus, dev->seq);
>         if (ret)
>                 return ret;
> @@ -682,6 +688,8 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>         struct zynq_gem_priv *priv = dev_get_priv(dev);
>         int node = dev_of_offset(dev);
>         const char *phy_mode;
> +       fdt_addr_t addr;
> +       int parent;
>
>         pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
>         priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
> @@ -690,10 +698,24 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>
>         priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, node,
>                                                     "phy-handle");
> -       if (priv->phy_of_handle > 0)
> +       if (priv->phy_of_handle > 0) {
>                 priv->phyaddr = fdtdec_get_int(gd->fdt_blob,
>                                         priv->phy_of_handle, "reg", -1);
>
> +               parent = fdt_parent_offset(gd->fdt_blob, priv->phy_of_handle);
> +               addr = fdtdec_get_addr(gd->fdt_blob, parent, "reg");
> +
> +               if (addr == FDT_ADDR_T_NONE) {
> +                       printf("MDIO bus not found %x %x, %x\n",
> +                              node, priv->phy_of_handle, parent);
> +                       return -ENODEV;
> +               }
> +
> +               priv->mdiobase = (struct zynq_gem_regs *)addr;
> +       } else {
> +               priv->mdiobase = priv->iobase;
> +       }
> +
>         phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
>         if (phy_mode)
>                 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
> @@ -706,8 +728,9 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>         priv->int_pcs = fdtdec_get_bool(gd->fdt_blob, node,
>                                         "is-internal-pcspma");
>
> -       printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
> -              priv->phyaddr, phy_string_for_interface(priv->interface));
> +       printf("ZYNQ GEM: %lx, mdio bus %lx, phyaddr %d, interface %s\n",
> +              (ulong)priv->iobase, (ulong)priv->mdiobase, priv->phyaddr,
> +              phy_string_for_interface(priv->interface));
>
>         return 0;
>  }
> --
> 1.9.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