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

Tomasz Gorochowik tgorochowik at antmicro.com
Wed Apr 4 08:36:10 UTC 2018


Joe, Michal,

Please allow me to include the patches I originally sent to Michal.

We are well aware of the fact that only one network interface is used to
boot
the board, but it is quite convenient to be able to plug the ethernet cable
to
any eth socket, and still be able to boot (assuming 'ethrotate' is set).

We also accept the fact that the patch not acceptable in its current form,
but
maybe you could point us in the right direction, Joe?

I think that the main advantage of our patch is that the mdio_alloc is
called
just once, not separately for each gem.

Just to note: we're also okay with the solution from Michal, but we'd like
to get
one of the patches to the official repo (or to Michals fork first for that
matter).
We're also willing to spend more time on that if you provide us some hints
on
how would you like us to proceed.

Thanks,
Tomasz

---
>From 718a7c7bfdbd4323bd47197c2d00cd215a3e8f74 Mon Sep 17 00:00:00 2001
From: Tomasz Gorochowik <tgorochowik at antmicro.com>
Date: Fri, 15 Dec 2017 12:03:34 +0100
Subject: [PATCH] net: zynq_gem: add zynq gem mdio bus driver

The purpose of this driver is to allow accessing multiple PHYs from
separate GEMs, but with a shared MDIO bus.

This commit explores the same idea as the Linux macb_mdio patch
submitted by Harini Katakam (Xilinx).

To make this driver usable with all the currently existing ZynqMP
platforms, and not to break regular Zynq support, the MDIO bus has to be
used as a virtual bus that wraps all the GEM interfaces that it is going
to be used by (thus the zynqmp.dtsi changes).

If the parent node of the GEM driver is something else than the MDIO bus
node - the driver will fallback to using built-in MDIO - this ensures
compatibility for current Zynq boards and ZynqMP boards that do not want
to use the shared MDIO functionality.

By default the 'compatible' property of the virtual bus node is set to
'simple-bus', so the child nodes get probed normally without the need to
modify any existing dts files for specific boards, but also to make the
MDIO bus instantiation easy.

To instantiate it, lets say for GEM0 and GEM3 and make both of them use
the MDIO bus from GEM0, the following lines have to be added to the main
devicetree file of the board:

  &mdio {
  compatible = "cdns,zynqmp-gem-mdio";
  reg = <0x0 0xff0b0000>;
  phy7: ethernet-phy at 7 {
  reg = <7>;
  };
  phy3: ethernet-phy at 3 {
  reg = <3>;
  };
  };

  &gem0 {
  status = "okay";
  phy-handle = <&phy3>;
  phy-mode = "rgmii-id";
  };

  &gem3 {
  status = "okay";
  phy-handle = <&phy7>;
  phy-mode = "rgmii-id";
  };

Note how the compatible string is changed to bind the device to the
gem-mdio driver. The reg value of the MDIO bus is defined to the address
of the GEM in which the MDIO resides (GEM0 in this case). Also note how
the phy handles are defined inside the mdio bus for clarity.

Signed-off-by: Tomasz Gorochowik <tgorochowik at antmicro.com>
---
 arch/arm/dts/zynqmp.dtsi    | 109
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------
 drivers/net/Makefile        |   2 +-
 drivers/net/zynq_gem.c      |  94
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
 drivers/net/zynq_gem.h      |   8 ++++++++
 drivers/net/zynq_gem_mdio.c |  95
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 221 insertions(+), 87 deletions(-)
 create mode 100644 drivers/net/zynq_gem.h
 create mode 100644 drivers/net/zynq_gem_mdio.c

diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index 6a5c902..7499e52 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -568,60 +568,67 @@
  power-domains = <&pd_nand>;
  };

- gem0: ethernet at ff0b0000 {
- compatible = "cdns,zynqmp-gem";
- status = "disabled";
- interrupt-parent = <&gic>;
- interrupts = <0 57 4>, <0 57 4>;
- reg = <0x0 0xff0b0000 0x0 0x1000>;
- clock-names = "pclk", "hclk", "tx_clk";
- #address-cells = <1>;
- #size-cells = <0>;
- #stream-id-cells = <1>;
- iommus = <&smmu 0x874>;
- power-domains = <&pd_eth0>;
- };
+ mdio: mdio {
+ compatible = "simple-bus";
+ status = "okay";
+ #address-cells = <2>;
+ #size-cells = <2>;

- gem1: ethernet at ff0c0000 {
- compatible = "cdns,zynqmp-gem";
- status = "disabled";
- interrupt-parent = <&gic>;
- interrupts = <0 59 4>, <0 59 4>;
- reg = <0x0 0xff0c0000 0x0 0x1000>;
- clock-names = "pclk", "hclk", "tx_clk";
- #address-cells = <1>;
- #size-cells = <0>;
- #stream-id-cells = <1>;
- iommus = <&smmu 0x875>;
- power-domains = <&pd_eth1>;
- };
+ gem0: ethernet at ff0b0000 {
+ compatible = "cdns,zynqmp-gem";
+ status = "disabled";
+ interrupt-parent = <&gic>;
+ interrupts = <0 57 4>, <0 57 4>;
+ reg = <0x0 0xff0b0000 0x0 0x1000>;
+ clock-names = "pclk", "hclk", "tx_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #stream-id-cells = <1>;
+ iommus = <&smmu 0x874>;
+ power-domains = <&pd_eth0>;
+ };

- gem2: ethernet at ff0d0000 {
- compatible = "cdns,zynqmp-gem";
- status = "disabled";
- interrupt-parent = <&gic>;
- interrupts = <0 61 4>, <0 61 4>;
- reg = <0x0 0xff0d0000 0x0 0x1000>;
- clock-names = "pclk", "hclk", "tx_clk";
- #address-cells = <1>;
- #size-cells = <0>;
- #stream-id-cells = <1>;
- iommus = <&smmu 0x876>;
- power-domains = <&pd_eth2>;
- };
+ gem1: ethernet at ff0c0000 {
+ compatible = "cdns,zynqmp-gem";
+ status = "disabled";
+ interrupt-parent = <&gic>;
+ interrupts = <0 59 4>, <0 59 4>;
+ reg = <0x0 0xff0c0000 0x0 0x1000>;
+ clock-names = "pclk", "hclk", "tx_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #stream-id-cells = <1>;
+ iommus = <&smmu 0x875>;
+ power-domains = <&pd_eth1>;
+ };

- gem3: ethernet at ff0e0000 {
- compatible = "cdns,zynqmp-gem";
- status = "disabled";
- interrupt-parent = <&gic>;
- interrupts = <0 63 4>, <0 63 4>;
- reg = <0x0 0xff0e0000 0x0 0x1000>;
- clock-names = "pclk", "hclk", "tx_clk";
- #address-cells = <1>;
- #size-cells = <0>;
- #stream-id-cells = <1>;
- iommus = <&smmu 0x877>;
- power-domains = <&pd_eth3>;
+ gem2: ethernet at ff0d0000 {
+ compatible = "cdns,zynqmp-gem";
+ status = "disabled";
+ interrupt-parent = <&gic>;
+ interrupts = <0 61 4>, <0 61 4>;
+ reg = <0x0 0xff0d0000 0x0 0x1000>;
+ clock-names = "pclk", "hclk", "tx_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #stream-id-cells = <1>;
+ iommus = <&smmu 0x876>;
+ power-domains = <&pd_eth2>;
+ };
+
+ gem3: ethernet at ff0e0000 {
+ compatible = "cdns,zynqmp-gem";
+ status = "disabled";
+ interrupt-parent = <&gic>;
+ interrupts = <0 63 4>, <0 63 4>;
+ reg = <0x0 0xff0e0000 0x0 0x1000>;
+ clock-names = "pclk", "hclk", "tx_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #stream-id-cells = <1>;
+ iommus = <&smmu 0x877>;
+ power-domains = <&pd_eth3>;
+ };
  };

  gpio: gpio at ff0a0000 {
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5702592..fd8a923 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -69,7 +69,7 @@ obj-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
 obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
 obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
  xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
-obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
+obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o zynq_gem_mdio.o
 obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/
 obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
 obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 3dec1ff..95d5a7d 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -27,6 +27,8 @@
 #include <asm-generic/errno.h>
 #include <clk.h>

+#include "zynq_gem.h"
+
 DECLARE_GLOBAL_DATA_PTR;

 /* Bit/mask specification */
@@ -182,12 +184,13 @@ struct zynq_gem_priv {
  struct phy_device *phydev;
  int phy_of_handle;
  struct mii_dev *bus;
+ bool shared_mdio;
 #ifdef CONFIG_CLK_ZYNQMP
  struct clk clk;
 #endif
 };

-static inline int mdio_wait(struct zynq_gem_regs *regs)
+inline int mdio_wait(struct zynq_gem_regs *regs)
 {
  u32 timeout = 20000;

@@ -206,11 +209,10 @@ static inline int mdio_wait(struct zynq_gem_regs
*regs)
  return 0;
 }

-static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32
regnum,
+static u32 phy_setup_op(struct zynq_gem_regs *regs, u32 phy_addr, u32
regnum,
  u32 op, u16 *data)
 {
  u32 mgtcr;
- struct zynq_gem_regs *regs = priv->iobase;

  if (mdio_wait(regs))
  return 1;
@@ -232,12 +234,12 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv,
u32 phy_addr, u32 regnum,
  return 0;
 }

-static u32 phyread(struct zynq_gem_priv *priv, u32 phy_addr,
+static u32 phyread(struct zynq_gem_regs *regs, u32 phy_addr,
     u32 regnum, u16 *val)
 {
  u32 ret;

- ret = phy_setup_op(priv, phy_addr, regnum,
+ ret = phy_setup_op(regs, phy_addr, regnum,
     ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);

  if (!ret)
@@ -247,13 +249,13 @@ static u32 phyread(struct zynq_gem_priv *priv, u32
phy_addr,
  return ret;
 }

-static u32 phywrite(struct zynq_gem_priv *priv, u32 phy_addr,
+static u32 phywrite(struct zynq_gem_regs *regs, u32 phy_addr,
      u32 regnum, u16 data)
 {
  debug("%s: phy_addr %d, regnum 0x%x, data 0x%x\n", __func__, phy_addr,
        regnum, data);

- return phy_setup_op(priv, phy_addr, regnum,
+ return phy_setup_op(regs, phy_addr, regnum,
      ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);
 }

@@ -264,7 +266,9 @@ static int phy_detection(struct udevice *dev)
  struct zynq_gem_priv *priv = dev->priv;

  if (priv->phyaddr != -1) {
- phyread(priv, priv->phyaddr, PHY_DETECT_REG, &phyreg);
+ phyreg = priv->bus->read(priv->bus, priv->phyaddr, 0,
+ PHY_DETECT_REG);
+
  if ((phyreg != 0xFFFF) &&
      ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  /* Found a valid PHY address */
@@ -282,7 +286,8 @@ static int phy_detection(struct udevice *dev)
  if (priv->phyaddr == -1) {
  /* detect the PHY address */
  for (i = 31; i >= 0; i--) {
- phyread(priv, i, PHY_DETECT_REG, &phyreg);
+ phyreg = priv->bus->read(priv->bus, i, 0,
+ PHY_DETECT_REG);
  if ((phyreg != 0xFFFF) &&
      ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  /* Found a valid PHY address */
@@ -330,7 +335,6 @@ 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;
  const u32 supported = SUPPORTED_10baseT_Half |
  SUPPORTED_10baseT_Full |
  SUPPORTED_100baseT_Half |
@@ -338,9 +342,6 @@ static int zynq_phy_init(struct udevice *dev)
  SUPPORTED_1000baseT_Half |
  SUPPORTED_1000baseT_Full;

- /* Enable only MDIO bus */
- writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, &regs->nwctrl);
-
  if (priv->interface != PHY_INTERFACE_MODE_SGMII) {
  ret = phy_detection(dev);
  if (ret) {
@@ -366,7 +367,7 @@ static int zynq_phy_init(struct udevice *dev)

 static int zynq_gem_init(struct udevice *dev)
 {
- u32 i, nwconfig;
+ u32 i, nwconfig, nwcontrol;
  int ret;
  unsigned long clk_rate = 0;
  struct zynq_gem_priv *priv = dev_get_priv(dev);
@@ -379,7 +380,15 @@ static int zynq_gem_init(struct udevice *dev)
  writel(0xFFFFFFFF, &regs->idr);

  /* Disable the receiver & transmitter */
- writel(0, &regs->nwctrl);
+ if (priv->shared_mdio) {
+ nwcontrol = readl(&regs->nwctrl);
+ nwcontrol &= ~ZYNQ_GEM_NWCTRL_RXEN_MASK;
+ nwcontrol &= ~ZYNQ_GEM_NWCTRL_TXEN_MASK;
+ } else {
+ nwcontrol = 0;
+ }
+ writel(nwcontrol, &regs->nwctrl);
+
  writel(0, &regs->txsr);
  writel(0, &regs->rxsr);
  writel(0, &regs->phymntnc);
@@ -412,8 +421,10 @@ static int zynq_gem_init(struct udevice *dev)
  /* Setup for DMA Configuration register */
  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);
+ if (!priv->shared_mdio) {
+ /* Enable MDIO */
+ setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
+ }

  /* Disable the second priority queue */
  dummy_tx_bd->addr = 0;
@@ -613,25 +624,24 @@ static int zynq_gem_read_rom_mac(struct udevice *dev)
  return retval;
 }

-static int zynq_gem_miiphy_read(struct mii_dev *bus, int addr,
- int devad, int reg)
+int zynq_gem_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
- struct zynq_gem_priv *priv = bus->priv;
+ struct zynq_gem_regs *regs = bus->priv;
  int ret;
  u16 val;

- ret = phyread(priv, addr, reg, &val);
+ ret = phyread(regs, addr, reg, &val);
  debug("%s 0x%x, 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val, ret);
  return val;
 }

-static int zynq_gem_miiphy_write(struct mii_dev *bus, int addr, int devad,
- int reg, u16 value)
+int zynq_gem_miiphy_write(struct mii_dev *bus, int addr, int devad, int
reg,
+   u16 value)
 {
- struct zynq_gem_priv *priv = bus->priv;
+ struct zynq_gem_regs *regs = bus->priv;

  debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, value);
- return phywrite(priv, addr, reg, value);
+ return phywrite(regs, addr, reg, value);
 }

 static int zynq_gem_probe(struct udevice *dev)
@@ -661,15 +671,18 @@ static int zynq_gem_probe(struct udevice *dev)
  }
 #endif

- priv->bus = mdio_alloc();
- priv->bus->read = zynq_gem_miiphy_read;
- priv->bus->write = zynq_gem_miiphy_write;
- priv->bus->priv = priv;
- strcpy(priv->bus->name, "gem");
+ if (!priv->shared_mdio) {
+ /* Initialize built-in MDIO */
+ priv->bus = mdio_alloc();
+ priv->bus->read = zynq_gem_miiphy_read;
+ priv->bus->write = zynq_gem_miiphy_write;
+ priv->bus->priv = priv->iobase;
+ strcpy(priv->bus->name, "gem");

- ret = mdio_register(priv->bus);
- if (ret)
- return ret;
+ ret = mdio_register(priv->bus);
+ if (ret)
+ return ret;
+ }

  return zynq_phy_init(dev);
 }
@@ -679,8 +692,13 @@ static int zynq_gem_remove(struct udevice *dev)
  struct zynq_gem_priv *priv = dev_get_priv(dev);

  free(priv->phydev);
- mdio_unregister(priv->bus);
- mdio_free(priv->bus);
+
+ if (priv->shared_mdio) {
+ mdio_unregister(priv->bus);
+ mdio_free(priv->bus);
+
+ free(dev->parent_platdata);
+ }

  return 0;
 }
@@ -706,6 +724,7 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
*dev)
  /* Hardcode for now */
  priv->emio = 0;
  priv->phyaddr = -1;
+ priv->shared_mdio = false;

  priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob,
  dev->of_offset, "phy-handle");
@@ -724,6 +743,11 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
*dev)

  priv->emio = fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "xlnx,emio");

+ /* Determine if we're connected to an external MDIO */
+ priv->bus = dev_get_parent_platdata(dev);
+ if (priv->bus)
+ priv->shared_mdio = true;
+
  printf("ZYNQ GEM: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase,
         priv->phyaddr, phy_string_for_interface(priv->interface));

diff --git a/drivers/net/zynq_gem.h b/drivers/net/zynq_gem.h
new file mode 100644
index 0000000..a9bf175
--- /dev/null
+++ b/drivers/net/zynq_gem.h
@@ -0,0 +1,8 @@
+#ifndef ZYNQ_GEM_H
+#define ZYNQ_GEM_H
+
+int zynq_gem_miiphy_read(struct mii_dev *bus, int addr, int devad, int
reg);
+int zynq_gem_miiphy_write(struct mii_dev *bus, int addr, int devad, int
reg,
+   u16 value);
+
+#endif
diff --git a/drivers/net/zynq_gem_mdio.c b/drivers/net/zynq_gem_mdio.c
new file mode 100644
index 0000000..1e4b091
--- /dev/null
+++ b/drivers/net/zynq_gem_mdio.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 Enclustra GmbH
+ * Author: Tomasz Gorochowik <tgorochowik at antmicro.com>
+ *
+ * The idea for this driver was based on a Linux macb_mdio
+ * driver by Harini Katakam, Xilinx
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm.h>
+#include <asm/io.h>
+#include <miiphy.h>
+
+#include "zynq_gem.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ZYNQ_GEM_MDIO_NWCTRL_MDEN_MASK 0x00000010 /* Enable MDIO port */
+
+static int zynq_gem_mdio_probe(struct udevice *dev)
+{
+ struct mii_dev *bus = dev_get_priv(dev);
+ u32 *nwctrl_reg = bus->priv;
+
+ setbits_le32(nwctrl_reg, ZYNQ_GEM_MDIO_NWCTRL_MDEN_MASK);
+
+ return 0;
+}
+
+static int zynq_gem_mdio_remove(struct udevice *dev)
+{
+ struct mii_dev *bus = dev_get_priv(dev);
+ u32 *nwctrl_reg = bus->priv;
+
+ clrbits_le32(nwctrl_reg, ZYNQ_GEM_MDIO_NWCTRL_MDEN_MASK);
+
+ /* Unregister and free mdio bus */
+ mdio_unregister(bus);
+ mdio_free(bus);
+
+ return 0;
+}
+
+static const struct udevice_id zynq_gem_mdio_ids[] = {
+ { .compatible = "cdns,zynqmp-gem-mdio" },
+ { }
+};
+
+static int zynq_gem_mdio_ofdata_to_platdata(struct udevice *dev)
+{
+ struct mii_dev *bus;
+
+ bus = mdio_alloc();
+ if (!bus)
+ return -ENOMEM;
+
+ sprintf(bus->name, "%s", "zynq_gem_mdio");
+ bus->read = zynq_gem_miiphy_read;
+ bus->write = zynq_gem_miiphy_write;
+
+ /* We use the fact that we only need a single register
+ * in this driver (network_control), the private data
+ * pointer holds its address directly
+ */
+ bus->priv = (void *)dev_get_addr(dev);
+ dev->priv = bus;
+
+ mdio_register(bus);
+
+ return 0;
+}
+
+static int zynq_gem_mdio_child_pre_probe(struct udevice *dev)
+{
+ struct udevice *pdev = dev_get_parent(dev);
+ struct mii_dev *bus = dev_get_priv(pdev);
+
+ dev->parent_platdata = bus;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(zynq_gem_mdio) = {
+ .name = "zynq_gem_mdio",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = zynq_gem_mdio_ids,
+ .ofdata_to_platdata = zynq_gem_mdio_ofdata_to_platdata,
+ .probe = zynq_gem_mdio_probe,
+ .remove = zynq_gem_mdio_remove,
+ .priv_auto_alloc_size = sizeof(struct mii_dev *),
+ .platdata_auto_alloc_size = sizeof(struct mii_dev *),
+ .per_child_platdata_auto_alloc_size = sizeof(struct mii_dev *),
+ .child_pre_probe = zynq_gem_mdio_child_pre_probe,
+};
--
libgit2 0.26.0



On Fri, Feb 16, 2018 at 8:24 PM, Joe Hershberger <joe.hershberger at gmail.com>
wrote:

> On Wed, Feb 7, 2018 at 1:46 AM, Michal Simek <michal.simek at xilinx.com>
> wrote:
> > On 6.2.2018 22:11, Joe Hershberger wrote:
> >> On Mon, Feb 5, 2018 at 1:17 AM, Michal Simek <michal.simek at xilinx.com>
> wrote:
> >>> Hi Joe,
> >>>
> >>> On 2.2.2018 20:35, Joe Hershberger wrote:
> >>>> 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.
> >>>
> >>> Is it really that different? There should be phy handle which is
> >>> pointing to actual phy and that should be enough to recognize parents
> >>> and IP responsible for MDIO bus.
> >>
> >> The point is different drivers express the relationship with varying
> >> levels of implication, so there are a number of ways people describe
> >> it.
> >
> > ok.
> >
> >>
> >>>>> 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.
> >>>
> >>> What exactly are you doing on 7020?
> >>
> >> We are using a single MDIO interface to connect the PHYs for 2 GEMs.
> >
> > And I expect you are using only one interface for boot right?
>
> That's right. Currently we only have one defined in U-Boot, but of
> course use both from Linux.
>
> -Joe
>



-- 
Tomasz Gorochowik
Antmicro Ltd | www.antmicro.com
Zwierzyniecka 3, 60-813 Poznan, Poland


More information about the U-Boot mailing list