Apparently when hooking up an Ethernet PHY using an RGMII interface some signals need a to have a small clock delay applied to them. The delays can be applied at various points: by the PHY, by the lengt of the traces on the board or by the MAC. Linux has an explanation her:
https://github.com/torvalds/linux/blob/master/Documentation/driver-api/phy/phy.rst which includes the description of the kernel interface to handle this. Part of this interface is exported into the device tree and ACPI properies to allow software configuration of the appropriate delays to happen. Unfortunately that means we have to deal with this as well. Below is a diff that adds support for the BCM54210E PHY that is used on the Raspberry Pi4. The idea is to pass acombination of the MIIF_RXID and MIIF_TXID flags to indicate the combination of delays that is desired: "rgmii" -> 0 "rgmii-rxid" -> MIIF_RXID "rgmii-txid" -> MIIF_TXID "rgmii-id" -> MIIF_RXID | MIIF_TXID The diff also replaces some magic numbers with proper defines since I added those in this diff. I can split that out. ok? Index: dev/mii/brgphy.c =================================================================== RCS file: /cvs/src/sys/dev/mii/brgphy.c,v retrieving revision 1.105 diff -u -p -r1.105 brgphy.c --- dev/mii/brgphy.c 19 Jul 2015 06:28:12 -0000 1.105 +++ dev/mii/brgphy.c 11 Apr 2020 19:48:59 -0000 @@ -92,6 +92,7 @@ void brgphy_crc_bug(struct mii_softc *); void brgphy_disable_early_dac(struct mii_softc *sc); void brgphy_jumbo_settings(struct mii_softc *); void brgphy_eth_wirespeed(struct mii_softc *); +void brgphy_bcm54xx_clock_delay(struct mii_softc *); const struct mii_phy_funcs brgphy_copper_funcs = { brgphy_service, brgphy_copper_status, brgphy_reset, @@ -180,6 +181,8 @@ static const struct mii_phydesc brgphys[ MII_STR_xxBROADCOM3_BCM57765 }, { MII_OUI_xxBROADCOM3, MII_MODEL_xxBROADCOM3_BCM57780, MII_STR_xxBROADCOM3_BCM57780 }, + { MII_OUI_xxBROADCOM4, MII_MODEL_xxBROADCOM4_BCM54210E, + MII_STR_xxBROADCOM4_BCM54210E }, { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5906, MII_STR_BROADCOM2_BCM5906 }, @@ -789,6 +792,12 @@ brgphy_reset(struct mii_softc *sc) break; } break; + case MII_OUI_xxBROADCOM4: + switch (sc->mii_model) { + case MII_MODEL_xxBROADCOM4_BCM54210E: + brgphy_bcm54xx_clock_delay(sc); + break; + } } /* Handle any bge (NetXtreme/NetLink) workarounds. */ @@ -1187,11 +1196,38 @@ brgphy_jumbo_settings(struct mii_softc * void brgphy_eth_wirespeed(struct mii_softc *sc) { - u_int32_t val; + uint16_t val; /* Enable Ethernet@Wirespeed */ - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); - val = PHY_READ(sc, BRGPHY_MII_AUXCTL); - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, - (val | (1 << 15) | (1 << 4))); + 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) & BRGPHY_AUXCTL_MISC_DATA_MASK; + val |= BRGPHY_AUXCTL_MISC_WIRESPEED_EN; + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, BRGPHY_AUXCTL_MISC_WRITE_EN | + BRGPHY_AUXCTL_SHADOW_MISC | val); +} + +void +brgphy_bcm54xx_clock_delay(struct mii_softc *sc) +{ + uint16_t val; + + 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) & BRGPHY_AUXCTL_MISC_DATA_MASK; + if (sc->mii_flags & MIIF_RXID) + 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) & BRGPHY_SHADOW_1C_DATA_MASK; + if (sc->mii_flags & MIIF_TXID) + 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); } Index: dev/mii/brgphyreg.h =================================================================== RCS file: /cvs/src/sys/dev/mii/brgphyreg.h,v retrieving revision 1.17 diff -u -p -r1.17 brgphyreg.h --- dev/mii/brgphyreg.h 19 Jul 2015 06:28:12 -0000 1.17 +++ dev/mii/brgphyreg.h 11 Apr 2020 19:48:59 -0000 @@ -195,6 +195,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). @@ -202,6 +213,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: dev/mii/miidevs =================================================================== RCS file: /cvs/src/sys/dev/mii/miidevs,v retrieving revision 1.128 diff -u -p -r1.128 miidevs --- dev/mii/miidevs 24 Sep 2019 14:35:22 -0000 1.128 +++ dev/mii/miidevs 11 Apr 2020 19:48:59 -0000 @@ -96,6 +96,7 @@ oui xxLEVEL1 0x1e0400 Level 1 /* Don't know what's going on here. */ oui xxBROADCOM2 0x0050ef Broadcom oui xxBROADCOM3 0x00d897 Broadcom +oui xxBROADCOM4 0x180361 Broadcom oui xxDAVICOM 0x006040 Davicom /* This is the OUI of the gigE PHY in the Realtek 8169S/8110S chips */ @@ -177,6 +178,7 @@ model BROADCOM BCM5222 0x0032 BCM5222 D model BROADCOM BCM5220 0x0033 BCM5220 10/100 PHY model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY model BROADCOM2 BCM5906 0x0004 BCM5906 10/100baseTX PHY +model xxBROADCOM4 BCM54210E 0x000a BCM54210E 10/100/1000baseT PHY /* Cicada PHYs (now owned by Vitesse) */ model xxCICADA CS8201B 0x0021 CS8201 10/100/1000TX PHY Index: dev/mii/miidevs.h =================================================================== RCS file: /cvs/src/sys/dev/mii/miidevs.h,v retrieving revision 1.131 diff -u -p -r1.131 miidevs.h --- dev/mii/miidevs.h 24 Sep 2019 14:36:00 -0000 1.131 +++ dev/mii/miidevs.h 11 Apr 2020 19:48:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: miidevs.h,v 1.131 2019/09/24 14:36:00 visa Exp $ */ +/* $OpenBSD$ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. @@ -103,6 +103,7 @@ /* Don't know what's going on here. */ #define MII_OUI_xxBROADCOM2 0x0050ef /* Broadcom */ #define MII_OUI_xxBROADCOM3 0x00d897 /* Broadcom */ +#define MII_OUI_xxBROADCOM4 0x180361 /* Broadcom */ #define MII_OUI_xxDAVICOM 0x006040 /* Davicom */ /* This is the OUI of the gigE PHY in the Realtek 8169S/8110S chips */ @@ -242,6 +243,8 @@ #define MII_STR_BROADCOM_BCM4401 "BCM4401 10/100baseTX PHY" #define MII_MODEL_BROADCOM2_BCM5906 0x0004 #define MII_STR_BROADCOM2_BCM5906 "BCM5906 10/100baseTX PHY" +#define MII_MODEL_xxBROADCOM4_BCM54210E 0x000a +#define MII_STR_xxBROADCOM4_BCM54210E "BCM54210E 10/100/1000baseT PHY" /* Cicada PHYs (now owned by Vitesse) */ #define MII_MODEL_xxCICADA_CS8201B 0x0021 Index: dev/mii/miivar.h =================================================================== RCS file: /cvs/src/sys/dev/mii/miivar.h,v retrieving revision 1.34 diff -u -p -r1.34 miivar.h --- dev/mii/miivar.h 12 Sep 2015 09:49:20 -0000 1.34 +++ dev/mii/miivar.h 11 Apr 2020 19:48:59 -0000 @@ -152,6 +152,8 @@ typedef struct mii_softc mii_softc_t; #define MIIF_DOPAUSE 0x0100 /* advertise PAUSE capability */ #define MIIF_IS_HPNA 0x0200 /* is a HomePNA device */ #define MIIF_FORCEANEG 0x0400 /* force autonegotiation */ +#define MIIF_RXID 0x0800 /* add Rx delay */ +#define MIIF_TXID 0x1000 /* add Tx delay */ #define MIIF_INHERIT_MASK (MIIF_NOISOLATE|MIIF_NOLOOP|MIIF_AUTOTSLEEP)