[PATCH rtems-libbsd 2/2] if_ffec: Allow PHY that is connected to other FFEC

Gedare Bloom gedare at rtems.org
Thu Jun 2 13:50:39 UTC 2022


On Thu, Jun 2, 2022 at 1:35 AM Christian MAUDERER
<christian.mauderer at embedded-brains.de> wrote:
>
> Am 01.06.22 um 14:50 schrieb Gedare Bloom:
> > Should this be upstreamed?
>
> I don't think so. The solution is quite device specific and has some
> restrictions like the right initialization order (like noted in the
> commit description). I don't think that FreeBSD will accept it.
>
> I have seen some discussions on FreeBSD that they think about a more
> generic approach. Basically that would make it necessary to split the
> MDIO part from the remaining Ethernet controller part and make it a
> separate driver. That would most likely make it necessary to change
> multiple or all Ethernet drivers. I assume that some-when someone at
> FreeBSD will add a solution like that. But till then, I think the
> slightly hacked solution that I did with this patch should work well
> enough for us.
>
OK, that makes sense. Anytime we have some creep in libbsd I would ask
this question. ;)

> >
> > On Mon, May 23, 2022 at 6:22 AM Christian Mauderer
> > <christian.mauderer at embedded-brains.de> wrote:
> >>
> >> The i.MX6UL (and some others from the i.MX family) have shared MDIO
> >> lines for multiple FFECs. This patch allows to use the MDIO interface
> >> from another Ethernet controller.
> >>
> >> Note that you have to make sure that the FFECs are initialized in the
> >> right order. Normally that can be done via FDT.
> >> ---
> >>   freebsd/sys/dev/ffec/if_ffec.c | 120 +++++++++++++++++++++++++++++++++
> >>   1 file changed, 120 insertions(+)
> >>
> >> diff --git a/freebsd/sys/dev/ffec/if_ffec.c b/freebsd/sys/dev/ffec/if_ffec.c
> >> index 4c1e147b..316e077c 100644
> >> --- a/freebsd/sys/dev/ffec/if_ffec.c
> >> +++ b/freebsd/sys/dev/ffec/if_ffec.c
> >> @@ -209,6 +209,11 @@ struct ffec_softc {
> >>          int             rx_ic_count;    /* RW, valid values 0..255 */
> >>          int             tx_ic_time;
> >>          int             tx_ic_count;
> >> +#ifdef __rtems__
> >> +
> >> +       device_t                mdio_device;
> >> +       struct mtx              mdio_mtx;
> >> +#endif /* __rtems__ */
> >>   };
> >>
> >>   static struct resource_spec irq_res_spec[MAX_IRQ_COUNT + 1] = {
> >> @@ -376,6 +381,13 @@ ffec_miibus_readreg(device_t dev, int phy, int reg)
> >>          int val;
> >>
> >>          sc = device_get_softc(dev);
> >> +#ifdef __rtems__
> >> +       if (sc->mdio_device) {
> >> +               return (MIIBUS_READREG(sc->mdio_device, phy, reg));
> >> +       }
> >> +
> >> +       mtx_lock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>
> >>          WR4(sc, FEC_IER_REG, FEC_IER_MII);
> >>
> >> @@ -386,11 +398,17 @@ ffec_miibus_readreg(device_t dev, int phy, int reg)
> >>
> >>          if (!ffec_miibus_iowait(sc)) {
> >>                  device_printf(dev, "timeout waiting for mii read\n");
> >> +#ifdef __rtems__
> >> +               mtx_unlock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>                  return (-1); /* All-ones is a symptom of bad mdio. */
> >>          }
> >>
> >>          val = RD4(sc, FEC_MMFR_REG) & FEC_MMFR_DATA_MASK;
> >>
> >> +#ifdef __rtems__
> >> +       mtx_unlock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>          return (val);
> >>   }
> >>
> >> @@ -400,6 +418,13 @@ ffec_miibus_writereg(device_t dev, int phy, int reg, int val)
> >>          struct ffec_softc *sc;
> >>
> >>          sc = device_get_softc(dev);
> >> +#ifdef __rtems__
> >> +       if (sc->mdio_device) {
> >> +               return (MIIBUS_WRITEREG(sc->mdio_device, phy, reg, val));
> >> +       }
> >> +
> >> +       mtx_lock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>
> >>          WR4(sc, FEC_IER_REG, FEC_IER_MII);
> >>
> >> @@ -411,9 +436,15 @@ ffec_miibus_writereg(device_t dev, int phy, int reg, int val)
> >>
> >>          if (!ffec_miibus_iowait(sc)) {
> >>                  device_printf(dev, "timeout waiting for mii write\n");
> >> +#ifdef __rtems__
> >> +               mtx_unlock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>                  return (-1);
> >>          }
> >>
> >> +#ifdef __rtems__
> >> +       mtx_unlock(&sc->mdio_mtx);
> >> +#endif /* __rtems__ */
> >>          return (0);
> >>   }
> >>
> >> @@ -1577,6 +1608,9 @@ ffec_detach(device_t dev)
> >>          if (sc->mem_res != NULL)
> >>                  bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
> >>
> >> +#ifdef __rtems__
> >> +       mtx_destroy(&sc->mtx);
> >> +#endif /* __rtems__ */
> >>          FFEC_LOCK_DESTROY(sc);
> >>          return (0);
> >>   }
> >> @@ -1726,6 +1760,80 @@ ffec_set_txic(struct ffec_softc *sc)
> >>          ffec_set_ic(sc, FEC_TXIC0_REG, sc->tx_ic_count, sc->tx_ic_time);
> >>   }
> >>
> >> +#ifdef __rtems__
> >> +int
> >> +ffec_get_phy_information(
> >> +       struct ffec_softc *sc,
> >> +       phandle_t node,
> >> +       device_t dev,
> >> +       int *phy_addr
> >> +)
> >> +{
> >> +       phandle_t phy_node;
> >> +       phandle_t parent_node;
> >> +       pcell_t phy_handle, phy_reg;
> >> +       device_t other;
> >> +       phandle_t xref;
> >> +
> >> +       /* Search for the phy-handle and get the address */
> >> +
> >> +       if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
> >> +           sizeof(phy_handle)) <= 0)
> >> +               return (ENXIO);
> >> +
> >> +       phy_node = OF_node_from_xref(phy_handle);
> >> +
> >> +       if (OF_getencprop(phy_node, "reg", (void *)&phy_reg,
> >> +           sizeof(phy_reg)) <= 0)
> >> +               return (ENXIO);
> >> +
> >> +       *phy_addr = phy_reg;
> >> +
> >> +       /* Detect whether PHY handle is connected to this or another FFEC. */
> >> +       parent_node = phy_node;
> >> +
> >> +       while (parent_node != 0) {
> >> +               if (parent_node == node) {
> >> +                       /* PHY is directly connected. That's easy. */
> >> +                       sc->mdio_device = NULL;
> >> +                       return 0;
> >> +               }
> >> +
> >> +               /*
> >> +                * Check whether the node is also an Ethernet controller. Do
> >> +                * that by just assuming that every Ethernet controller has a
> >> +                * PHY attached to it.
> >> +                */
> >> +               if (OF_getencprop(parent_node, "phy-handle",
> >> +                   (void *)&phy_handle, sizeof(phy_handle)) > 0) {
> >> +                       /*
> >> +                        * Try to find the device of the other Ethernet
> >> +                        * controller and use that for MDIO communication.
> >> +                        * Note: This is not really a nice workaround but it
> >> +                        * works.
> >> +                        */
> >> +                       xref = OF_xref_from_node(parent_node);
> >> +                       if (xref == 0) {
> >> +                               device_printf(dev,
> >> +                                   "Couldn't get device that handles PHY\n");
> >> +                               return (ENXIO);
> >> +                       }
> >> +                       other = OF_device_from_xref(xref);
> >> +                       if (other == 0) {
> >> +                               device_printf(dev,
> >> +                                   "Couldn't get device that handles PHY\n");
> >> +                               return (ENXIO);
> >> +                       }
> >> +                       sc->mdio_device = other;
> >> +                       return 0;
> >> +               }
> >> +
> >> +               parent_node = OF_parent(parent_node);
> >> +       }
> >> +       return (ENXIO);
> >> +}
> >> +
> >> +#endif /* __rtems__ */
> >>   static int
> >>   ffec_attach(device_t dev)
> >>   {
> >> @@ -1743,6 +1851,10 @@ ffec_attach(device_t dev)
> >>          sc->dev = dev;
> >>
> >>          FFEC_LOCK_INIT(sc);
> >> +#ifdef __rtems__
> >> +       mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
> >> +           MTX_NETWORK_LOCK, MTX_DEF);
> >> +#endif /* __rtems__ */
> >>
> >>          /*
> >>           * There are differences in the implementation and features of the FEC
> >> @@ -2047,9 +2159,17 @@ ffec_attach(device_t dev)
> >>          ffec_miigasket_setup(sc);
> >>
> >>          /* Attach the mii driver. */
> >> +#ifdef __rtems__
> >> +       OF_device_register_xref(OF_xref_from_node(ofw_node), dev);
> >> +       if (ffec_get_phy_information(sc, ofw_node, dev, &phynum) != 0) {
> >> +               phynum = MII_PHY_ANY;
> >> +       }
> >> +       (void) dummy;
> >> +#else /* __rtems__ */
> >>          if (fdt_get_phyaddr(ofw_node, dev, &phynum, &dummy) != 0) {
> >>                  phynum = MII_PHY_ANY;
> >>          }
> >> +#endif /* __rtems__ */
> >>          error = mii_attach(dev, &sc->miibus, ifp, ffec_media_change,
> >>              ffec_media_status, BMSR_DEFCAPMASK, phynum, MII_OFFSET_ANY,
> >>              (sc->fecflags & FECTYPE_MVF) ? MIIF_FORCEANEG : 0);
> >> --
> >> 2.35.3
> >>
> >> _______________________________________________
> >> devel mailing list
> >> devel at rtems.org
> >> http://lists.rtems.org/mailman/listinfo/devel
>
> --
> --------------------------------------------
> embedded brains GmbH
> Herr Christian MAUDERER
> Dornierstr. 4
> 82178 Puchheim
> Germany
> email: christian.mauderer at embedded-brains.de
> phone: +49-89-18 94 741 - 18
> fax:   +49-89-18 94 741 - 08
>
> Registergericht: Amtsgericht München
> Registernummer: HRB 157899
> Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
> Unsere Datenschutzerklärung finden Sie hier:
> https://embedded-brains.de/datenschutzerklaerung/


More information about the devel mailing list