On Wed, Jul 05, 2023 at 01:13:34PM +0200, Mark Kettenis wrote:
> > Date: Wed, 5 Jul 2023 12:46:36 +0300
> > From: Jonathan Matthew <[email protected]>
> >
> > 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?
>
> Is there a reason why you structured this differently than how this is
> done for dwqe(4)?
I did this quite a while ago, so I'm not completely sure, but I think what
happened
is that I based it on an earlier version of the dwqe diff. Here's a new
version that
looks a lot more like how dwqe does it:
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 13:03:47 -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;
@@ -457,6 +458,30 @@ dwge_attach(struct device *parent, struc
/* Reset PHY */
dwge_reset_phy(sc);
+ node = OF_getnodebyname(faa->fa_node, "fixed-link");
+ if (node) {
+ 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)
sc->sc_clk = GMAC_GMII_ADDR_CR_DIV_124;
@@ -479,7 +504,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 +600,23 @@ 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);
+
+ /* force a configuration of the clocks/mac */
+ sc->sc_mii.mii_statchg(self);
+ }
if_attach(ifp);
ether_ifattach(ifp);
@@ -759,7 +792,10 @@ dwge_ioctl(struct ifnet *ifp, u_long cmd
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
+ if (sc->sc_fixed_media != 0)
+ error = ENOTTY;
+ else
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
break;
case SIOCGIFRXR:
@@ -858,11 +894,16 @@ dwge_mii_statchg(struct device *self)
{
struct dwge_softc *sc = (void *)self;
uint32_t conf;
+ uint64_t 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)) {
+ 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_1000_SX:
case IFM_1000_LX:
case IFM_1000_CX:
@@ -886,7 +927,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? */
@@ -1178,7 +1219,8 @@ dwge_up(struct dwge_softc *sc)
dwge_write(sc, GMAC_MAC_CONF, dwge_read(sc, GMAC_MAC_CONF) |
GMAC_MAC_CONF_TE | GMAC_MAC_CONF_RE);
- timeout_add_sec(&sc->sc_tick, 1);
+ if (sc->sc_fixed_media == 0)
+ timeout_add_sec(&sc->sc_tick, 1);
}
void
@@ -1190,7 +1232,8 @@ dwge_down(struct dwge_softc *sc)
int i;
timeout_del(&sc->sc_rxto);
- timeout_del(&sc->sc_tick);
+ if (sc->sc_fixed_media == 0)
+ timeout_del(&sc->sc_tick);
ifp->if_flags &= ~IFF_RUNNING;
ifq_clr_oactive(&ifp->if_snd);
@@ -1679,6 +1722,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 +1731,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;