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 = <&reg_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;

Reply via email to