Index: sys/arm64/broadcom/genet/if_genet.c =================================================================== --- sys/arm64/broadcom/genet/if_genet.c +++ sys/arm64/broadcom/genet/if_genet.c @@ -237,7 +237,7 @@ { struct ether_addr eaddr; struct gen_softc *sc; - int major, minor, error; + int major, minor, error, mii_flags; bool eaddr_found; sc = device_get_softc(dev); @@ -315,9 +315,24 @@ if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); /* Attach MII driver */ + mii_flags = 0; + switch (sc->phy_mode) + { + case MII_CONTYPE_RGMII_ID: + mii_flags |= MIIF_RX_DELAY | MIIF_TX_DELAY; + break; + case MII_CONTYPE_RGMII_RXID: + mii_flags |= MIIF_RX_DELAY; + break; + case MII_CONTYPE_RGMII_TXID: + mii_flags |= MIIF_TX_DELAY; + break; + default: + break; + } error = mii_attach(dev, &sc->miibus, sc->ifp, gen_media_change, gen_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, - MIIF_DOPAUSE); + mii_flags); if (error != 0) { device_printf(dev, "cannot attach PHY\n"); goto fail; @@ -371,6 +386,7 @@ switch (type) { case MII_CONTYPE_RGMII: + case MII_CONTYPE_RGMII_ID: case MII_CONTYPE_RGMII_RXID: case MII_CONTYPE_RGMII_TXID: sc->phy_mode = type; @@ -791,10 +807,17 @@ if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) return; - if (sc->phy_mode == MII_CONTYPE_RGMII || - sc->phy_mode == MII_CONTYPE_RGMII_RXID) - WR4(sc, GENET_SYS_PORT_CTRL, - GENET_SYS_PORT_MODE_EXT_GPHY); + switch (sc->phy_mode) + { + case MII_CONTYPE_RGMII: + case MII_CONTYPE_RGMII_ID: + case MII_CONTYPE_RGMII_RXID: + case MII_CONTYPE_RGMII_TXID: + WR4(sc, GENET_SYS_PORT_CTRL, GENET_SYS_PORT_MODE_EXT_GPHY); + break; + default: + WR4(sc, GENET_SYS_PORT_CTRL, 0); + } gen_set_enaddr(sc); @@ -1649,6 +1672,8 @@ val |= GENET_EXT_RGMII_OOB_RGMII_MODE_EN; if (sc->phy_mode == MII_CONTYPE_RGMII) val |= GENET_EXT_RGMII_OOB_ID_MODE_DISABLE; + else + val &= ~GENET_EXT_RGMII_OOB_ID_MODE_DISABLE; WR4(sc, GENET_EXT_RGMII_OOB_CTRL, val); val = RD4(sc, GENET_UMAC_CMD); Index: sys/dev/mii/brgphy.c =================================================================== --- sys/dev/mii/brgphy.c +++ sys/dev/mii/brgphy.c @@ -115,6 +115,7 @@ static void brgphy_fixup_crc_bug(struct mii_softc *); static void brgphy_fixup_jitter_bug(struct mii_softc *); static void brgphy_ethernet_wirespeed(struct mii_softc *); +static void brgphy_bcm54xx_clock_delay(struct mii_softc *); static void brgphy_jumbo_settings(struct mii_softc *, u_long); static const struct mii_phydesc brgphys[] = { @@ -158,6 +159,7 @@ MII_PHY_DESC(BROADCOM3, BCM5720C), MII_PHY_DESC(BROADCOM3, BCM57765), MII_PHY_DESC(BROADCOM3, BCM57780), + MII_PHY_DESC(BROADCOM4, BCM54213PE), MII_PHY_DESC(BROADCOM4, BCM5725C), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906), MII_PHY_END @@ -414,6 +416,12 @@ break; } break; + case MII_OUI_BROADCOM4: + switch (sc->mii_mpd_model) { + case MII_MODEL_BROADCOM4_BCM54213PE: + brgphy_bcm54xx_clock_delay(sc); + break; + } } } mii_phy_update(sc, cmd); @@ -863,6 +871,37 @@ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); } +static void +brgphy_bcm54xx_clock_delay(struct mii_softc *sc) +{ + uint16_t val; + + if (!(sc->mii_flags & (MIIF_RX_DELAY | MIIF_TX_DELAY))) + /* Adjusting the clocks in rgmii mode causes packet losses. */ + return; + + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_SHADOW_MISC | + BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT); + val = PHY_READ(sc, BRGPHY_MII_AUXCTL); + val &= BRGPHY_AUXCTL_MISC_DATA_MASK; + if (sc->mii_flags & MIIF_RX_DELAY) + val |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN; + else + val &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN; + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_MISC_WRITE_EN | + BRGPHY_AUXCTL_SHADOW_MISC | val); + + PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_CLK_CTRL); + val = PHY_READ(sc, BRGPHY_MII_SHADOW_1C); + val &= BRGPHY_SHADOW_1C_DATA_MASK; + if (sc->mii_flags & MIIF_TX_DELAY) + val |= BRGPHY_SHADOW_1C_GTXCLK_EN; + else + val &= ~BRGPHY_SHADOW_1C_GTXCLK_EN; + PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_WRITE_EN | + BRGPHY_SHADOW_1C_CLK_CTRL | val); +} + static void brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) { Index: sys/dev/mii/brgphyreg.h =================================================================== --- sys/dev/mii/brgphyreg.h +++ sys/dev/mii/brgphyreg.h @@ -293,6 +293,17 @@ /* Begin: PHY register values for the 5706 PHY */ /*******************************************************/ +/* + * Aux control shadow register, bits 0-2 select function (0x00 to + * 0x07). + */ +#define BRGPHY_AUXCTL_SHADOW_MISC 0x07 +#define BRGPHY_AUXCTL_MISC_DATA_MASK 0x7ff8 +#define BRGPHY_AUXCTL_MISC_READ_SHIFT 12 +#define BRGPHY_AUXCTL_MISC_WRITE_EN 0x8000 +#define BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN 0x0200 +#define BRGPHY_AUXCTL_MISC_WIRESPEED_EN 0x0010 + /* * Shadow register 0x1C, bit 15 is write enable, * bits 14-10 select function (0x00 to 0x1F). @@ -300,6 +311,11 @@ #define BRGPHY_MII_SHADOW_1C 0x1C #define BRGPHY_SHADOW_1C_WRITE_EN 0x8000 #define BRGPHY_SHADOW_1C_SELECT_MASK 0x7C00 +#define BRGPHY_SHADOW_1C_DATA_MASK 0x03FF + +/* Shadow 0x1C Clock Alignment Control Register (select value 0x03) */ +#define BRGPHY_SHADOW_1C_CLK_CTRL (0x03 << 10) +#define BRGPHY_SHADOW_1C_GTXCLK_EN 0x0200 /* Shadow 0x1C Mode Control Register (select value 0x1F) */ #define BRGPHY_SHADOW_1C_MODE_CTRL (0x1F << 10) Index: sys/dev/mii/miidevs =================================================================== --- sys/dev/mii/miidevs +++ sys/dev/mii/miidevs @@ -196,6 +196,7 @@ model BROADCOM3 BCM5719C 0x0022 BCM5719C 1000BASE-T media interface model BROADCOM3 BCM57765 0x0024 BCM57765 1000BASE-T media interface model BROADCOM3 BCM5720C 0x0036 BCM5720C 1000BASE-T media interface +model BROADCOM4 BCM54213PE 0x000a BCM54213PE 1000BASE-T media interface model BROADCOM4 BCM5725C 0x0038 BCM5725C 1000BASE-T media interface model xxBROADCOM_ALT1 BCM5906 0x0004 BCM5906 10/100baseTX media interface Index: sys/dev/mii/miivar.h =================================================================== --- sys/dev/mii/miivar.h +++ sys/dev/mii/miivar.h @@ -134,6 +134,8 @@ #define MIIF_DOPAUSE 0x00000100 /* advertise PAUSE capability */ #define MIIF_IS_HPNA 0x00000200 /* is a HomePNA device */ #define MIIF_FORCEANEG 0x00000400 /* force auto-negotiation */ +#define MIIF_RX_DELAY 0x00000800 /* add RX delay */ +#define MIIF_TX_DELAY 0x00001000 /* add TX delay */ #define MIIF_NOMANPAUSE 0x00100000 /* no manual PAUSE selection */ #define MIIF_FORCEPAUSE 0x00200000 /* force PAUSE advertisement */ #define MIIF_MACPRIV0 0x01000000 /* private to the MAC driver */