[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(®s->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, ®s->nwctrl);
> + writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s_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, ®s->dmacr);
>
> /* Setup for Network Control register, MDIO, Rx and Tx enable */
> - setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
> + setbits_le32(®s_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