On the Banana Pi R1 (aka Lamobo R1), the dwge interface on the soc is connected to a broadcom switch chip. It looks like this in the device tree:
&gmac { pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; phy-mode = "rgmii"; phy-supply = <®_gmac_3v3>; status = "okay"; fixed-link { speed = <1000>; full-duplex; }; mdio { ... } }; This diff makes the fixed-link part work, setting the interface's link state to up and the media type to IFM_1000_T|IFM_FDX instead of trying to attach a phy. After setting the media type, we need to call mii_statchg() to configure the MAC appropriately. ok? Index: if_dwge.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/if_dwge.c,v retrieving revision 1.16 diff -u -p -r1.16 if_dwge.c --- if_dwge.c 25 Jun 2023 22:36:09 -0000 1.16 +++ if_dwge.c 5 Jul 2023 09:16:41 -0000 @@ -271,6 +271,7 @@ struct dwge_softc { #define sc_lladdr sc_ac.ac_enaddr struct mii_data sc_mii; #define sc_media sc_mii.mii_media + uint64_t sc_fixed_media; int sc_link; int sc_phyloc; int sc_force_thresh_dma_mode; @@ -386,7 +387,7 @@ dwge_attach(struct device *parent, struc { struct dwge_softc *sc = (void *)self; struct fdt_attach_args *faa = aux; - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_ac.ac_if; uint32_t phy, phy_supply; uint32_t axi_config; uint32_t mode, pbl; @@ -403,16 +404,6 @@ dwge_attach(struct device *parent, struc } sc->sc_dmat = faa->fa_dmat; - /* Lookup PHY. */ - phy = OF_getpropint(faa->fa_node, "phy", 0); - if (phy == 0) - phy = OF_getpropint(faa->fa_node, "phy-handle", 0); - node = OF_getnodebyphandle(phy); - if (node) - sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY); - else - sc->sc_phyloc = MII_PHY_ANY; - pinctrl_byname(faa->fa_node, "default"); /* Enable clocks. */ @@ -449,13 +440,48 @@ dwge_attach(struct device *parent, struc if (OF_is_compatible(faa->fa_node, "starfive,jh7100-gmac")) sc->sc_defrag = 1; - /* Power up PHY. */ - phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0); - if (phy_supply) - regulator_enable(phy_supply); + node = OF_getnodebyname(faa->fa_node, "fixed-link"); + if (node == 0) { + /* Lookup PHY. */ + phy = OF_getpropint(faa->fa_node, "phy", 0); + if (phy == 0) + phy = OF_getpropint(faa->fa_node, "phy-handle", 0); + node = OF_getnodebyphandle(phy); + if (node) + sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY); + else + sc->sc_phyloc = MII_PHY_ANY; + + /* Power up PHY. */ + phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0); + if (phy_supply) + regulator_enable(phy_supply); - /* Reset PHY */ - dwge_reset_phy(sc); + /* Reset PHY */ + dwge_reset_phy(sc); + } else { + ifp->if_baudrate = IF_Mbps(OF_getpropint(node, + "speed", 0)); + + switch (OF_getpropint(node, "speed", 0)) { + case 1000: + sc->sc_fixed_media = IFM_ETHER | IFM_1000_T; + break; + case 100: + sc->sc_fixed_media = IFM_ETHER | IFM_100_TX; + break; + default: + sc->sc_fixed_media = IFM_ETHER | IFM_AUTO; + break; + } + + if (OF_getpropbool(node, "full-duplex")) { + ifp->if_link_state = LINK_STATE_FULL_DUPLEX; + sc->sc_fixed_media |= IFM_FDX; + } else { + ifp->if_link_state = LINK_STATE_UP; + } + } sc->sc_clk = clock_get_frequency(faa->fa_node, "stmmaceth"); if (sc->sc_clk > 250000000) @@ -479,7 +505,6 @@ dwge_attach(struct device *parent, struc timeout_set(&sc->sc_tick, dwge_tick, sc); timeout_set(&sc->sc_rxto, dwge_rxtick, sc); - ifp = &sc->sc_ac.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_xflags = IFXF_MPSAFE; @@ -576,14 +601,21 @@ dwge_attach(struct device *parent, struc dwge_write(sc, GMAC_AXI_BUS_MODE, mode); } - mii_attach(self, &sc->sc_mii, 0xffffffff, sc->sc_phyloc, - (sc->sc_phyloc == MII_PHY_ANY) ? 0 : MII_OFFSET_ANY, 0); - if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { - printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); - ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); - ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); - } else - ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); + if (sc->sc_fixed_media == 0) { + mii_attach(self, &sc->sc_mii, 0xffffffff, sc->sc_phyloc, + (sc->sc_phyloc == MII_PHY_ANY) ? 0 : MII_OFFSET_ANY, 0); + if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { + printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); + ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, + NULL); + ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); + } else + ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); + } else { + ifmedia_add(&sc->sc_media, sc->sc_fixed_media, 0, NULL); + ifmedia_set(&sc->sc_media, sc->sc_fixed_media); + sc->sc_mii.mii_statchg(self); + } if_attach(ifp); ether_ifattach(ifp); @@ -804,7 +836,10 @@ dwge_media_status(struct ifnet *ifp, str { struct dwge_softc *sc = ifp->if_softc; - if (LIST_FIRST(&sc->sc_mii.mii_phys)) { + if (sc->sc_fixed_media != 0) { + ifmr->ifm_active = sc->sc_fixed_media; + ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; + } else if (LIST_FIRST(&sc->sc_mii.mii_phys)) { mii_pollstat(&sc->sc_mii); ifmr->ifm_active = sc->sc_mii.mii_media_active; ifmr->ifm_status = sc->sc_mii.mii_media_status; @@ -858,11 +893,16 @@ dwge_mii_statchg(struct device *self) { struct dwge_softc *sc = (void *)self; uint32_t conf; + uint64_t media_active; + + media_active = sc->sc_fixed_media; + if (media_active == 0) + media_active = sc->sc_mii.mii_media_active; conf = dwge_read(sc, GMAC_MAC_CONF); conf &= ~(GMAC_MAC_CONF_PS | GMAC_MAC_CONF_FES); - switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { + switch (IFM_SUBTYPE(media_active)) { case IFM_1000_SX: case IFM_1000_LX: case IFM_1000_CX: @@ -886,7 +926,7 @@ dwge_mii_statchg(struct device *self) return; conf &= ~GMAC_MAC_CONF_DM; - if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX) + if ((media_active & IFM_GMASK) == IFM_FDX) conf |= GMAC_MAC_CONF_DM; /* XXX: RX/TX flow control? */ @@ -1679,6 +1719,7 @@ dwge_mii_statchg_rockchip(struct device struct regmap *rm; uint32_t grf; uint32_t gmac_clk_sel = 0; + uint64_t media_active; dwge_mii_statchg(self); @@ -1687,7 +1728,11 @@ dwge_mii_statchg_rockchip(struct device if (rm == NULL) return; - switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) { + media_active = sc->sc_fixed_media; + if (media_active == 0) + media_active = sc->sc_mii.mii_media_active; + + switch (IFM_SUBTYPE(media_active)) { case IFM_10_T: gmac_clk_sel = sc->sc_clk_sel_2_5; break;