handle fixed-link configuration in the device tree.
authordlg <dlg@openbsd.org>
Mon, 24 Apr 2023 01:33:32 +0000 (01:33 +0000)
committerdlg <dlg@openbsd.org>
Mon, 24 Apr 2023 01:33:32 +0000 (01:33 +0000)
if fixed-link is present, populate the interface baudrate and link
status (full duplex or half duplex), and then call the statch handler
to apply that config to the MAC. if fixed-link is specified then
do not attach a phy.

note that phy lookup and reset still occurs in case the device tree
still uses the deprecated snps,reset-gpio properties. the fixed
link port on the bpi r2 pro is connected to a switch chip (which
is not really a phy) that needs needs a reset provided by the
snps,reset-gpio handling. an improved device tree would have the
reset properties on the switch node so it could do its own reset,
but we can't have nice things can we?

tested on a nanopi r5s, which has a phy but no fixed-link config,
and a banana pi bpi-r2 pro, which has both (cos it has two dwqes,
one with a phy and one without).

sys/dev/fdt/if_dwqe_fdt.c
sys/dev/ic/dwqe.c
sys/dev/ic/dwqevar.h

index 0da1055..f189524 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_dwqe_fdt.c,v 1.10 2023/04/22 05:01:44 dlg Exp $    */
+/*     $OpenBSD: if_dwqe_fdt.c,v 1.11 2023/04/24 01:33:32 dlg Exp $    */
 /*
  * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
  * Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
@@ -89,7 +89,7 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
        char phy_mode[16] = { 0 };
        uint32_t phy, phy_supply;
        uint32_t axi_config;
-       struct ifnet *ifp;
+       struct ifnet *ifp = &sc->sc_ac.ac_if;
        int i, node;
 
        sc->sc_node = faa->fa_node;
@@ -164,6 +164,15 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
        /* Reset PHY */
        dwqe_reset_phy(sc, phy);
 
+       node = OF_getnodebyname(sc->sc_node, "fixed-link");
+       if (node) {
+               sc->sc_fixed_link = 1;
+
+               ifp->if_baudrate = IF_Mbps(OF_getpropint(node, "speed", 0));
+               ifp->if_link_state = OF_getpropbool(node, "full-duplex") ?
+                   LINK_STATE_FULL_DUPLEX : LINK_STATE_HALF_DUPLEX;
+       }
+
        sc->sc_clk = clock_get_frequency(faa->fa_node, "stmmaceth");
        if (sc->sc_clk > 500000000)
                sc->sc_clk = GMAC_MAC_MDIO_ADDR_CR_500_800;
@@ -227,10 +236,13 @@ dwqe_fdt_attach(struct device *parent, struct device *self, void *aux)
        if (sc->sc_ih == NULL)
                printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
 
-       ifp = &sc->sc_ac.ac_if;
        sc->sc_ifd.if_node = faa->fa_node;
        sc->sc_ifd.if_ifp = ifp;
        if_register(&sc->sc_ifd);
+
+       /* force a configuraton of the clocks/mac */
+       if (sc->sc_fixed_link)
+               sc->sc_mii.mii_statchg(self);
 }
 
 void
index 82e5581..2ecd3e8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dwqe.c,v 1.7 2023/04/23 06:22:15 dlg Exp $    */
+/*     $OpenBSD: dwqe.c,v 1.8 2023/04/24 01:33:32 dlg Exp $    */
 /*
  * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
  * Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
@@ -74,6 +74,7 @@ void  dwqe_watchdog(struct ifnet *);
 int    dwqe_media_change(struct ifnet *);
 void   dwqe_media_status(struct ifnet *, struct ifmediareq *);
 
+void   dwqe_mii_attach(struct dwqe_softc *);
 int    dwqe_mii_readreg(struct device *, int, int);
 void   dwqe_mii_writereg(struct device *, int, int, int);
 void   dwqe_mii_statchg(struct device *);
@@ -106,7 +107,6 @@ dwqe_attach(struct dwqe_softc *sc)
 {
        struct ifnet *ifp;
        uint32_t version, mode;
-       int mii_flags = 0;
        int i;
 
        version = dwqe_read(sc, GMAC_VERSION);
@@ -213,6 +213,24 @@ dwqe_attach(struct dwqe_softc *sc)
                dwqe_write(sc, GMAC_SYS_BUS_MODE, mode);
        }
 
+       if (!sc->sc_fixed_link)
+               dwqe_mii_attach(sc);
+
+       if_attach(ifp);
+       ether_ifattach(ifp);
+
+       /* Disable interrupts. */
+       dwqe_write(sc, GMAC_INT_EN, 0);
+       dwqe_write(sc, GMAC_CHAN_INTR_ENA(0), 0);
+
+       return 0;
+}
+
+void
+dwqe_mii_attach(struct dwqe_softc *sc)
+{
+       int mii_flags = 0;
+
        switch (sc->sc_phy_mode) {
        case DWQE_PHY_MODE_RGMII:
                mii_flags |= MIIF_SETDELAY;
@@ -238,15 +256,6 @@ dwqe_attach(struct dwqe_softc *sc)
                ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
        } else
                ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
-
-       if_attach(ifp);
-       ether_ifattach(ifp);
-
-       /* Disable interrupts. */
-       dwqe_write(sc, GMAC_INT_EN, 0);
-       dwqe_write(sc, GMAC_CHAN_INTR_ENA(0), 0);
-
-       return 0;
 }
 
 uint32_t
@@ -373,7 +382,10 @@ dwqe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
 
        case SIOCGIFMEDIA:
        case SIOCSIFMEDIA:
-               error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
+               if (sc->sc_fixed_link)
+                       error = ENOTTY;
+               else
+                       error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                break;
 
        case SIOCGIFRXR:
@@ -824,7 +836,8 @@ dwqe_up(struct dwqe_softc *sc)
            GMAC_CHAN_INTR_ENA_RIE |
            GMAC_CHAN_INTR_ENA_TIE);
 
-       timeout_add_sec(&sc->sc_phy_tick, 1);
+       if (!sc->sc_fixed_link)
+               timeout_add_sec(&sc->sc_phy_tick, 1);
 }
 
 void
@@ -836,7 +849,8 @@ dwqe_down(struct dwqe_softc *sc)
        int i;
 
        timeout_del(&sc->sc_rxto);
-       timeout_del(&sc->sc_phy_tick);
+       if (!sc->sc_fixed_link)
+               timeout_del(&sc->sc_phy_tick);
 
        ifp->if_flags &= ~IFF_RUNNING;
        ifq_clr_oactive(&ifp->if_snd);
index bdf0e3e..69e95a3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dwqevar.h,v 1.5 2023/04/23 06:22:15 dlg Exp $ */
+/*     $OpenBSD: dwqevar.h,v 1.6 2023/04/24 01:33:32 dlg Exp $ */
 /*
  * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
  * Copyright (c) 2017, 2022 Patrick Wildt <patrick@blueri.se>
@@ -63,6 +63,7 @@ struct dwqe_softc {
        int                     sc_phyloc;
        enum dwqe_phy_mode      sc_phy_mode;
        struct timeout          sc_phy_tick;
+       int                     sc_fixed_link;
 
        struct dwqe_dmamem      *sc_txring;
        struct dwqe_buf         *sc_txbuf;