Add support for bcm54213PE in brgphy.

This chip is used in the Rasperry Pi 4, and is supported by the if_genet
driver. Currently we use the ukphy mii driver, this patch switches over
to the brgphy mii driver instead. To support the rgmii-rxid phy mode,
which is now the default in the Linux dtb, we add support for clock
skewing.

These changes are taken from OpenBSD and NetBSD, except for the bailout
in brgphy_bcm54xx_clock_delay() in rgmii mode, which was found necessary
after testing.

Submitted by:	Robert Crowston, crowston at protomail.com
Differential Revision:	https://reviews.freebsd.org/D25251
This commit is contained in:
Mike Karels 2020-06-18 23:57:10 +00:00
parent 0a0c18180c
commit 349eddbd07
5 changed files with 89 additions and 6 deletions

View File

@ -237,7 +237,7 @@ gen_attach(device_t dev)
{
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 @@ gen_attach(device_t dev)
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 @@ gen_get_phy_mode(device_t dev)
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 @@ gen_init_locked(struct gen_softc *sc)
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 @@ gen_update_link_locked(struct gen_softc *sc)
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);

View File

@ -115,6 +115,7 @@ static void brgphy_fixup_ber_bug(struct mii_softc *);
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 @@ static const struct mii_phydesc brgphys[] = {
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 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
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 @@ brgphy_ethernet_wirespeed(struct mii_softc *sc)
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)
{

View File

@ -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)

View File

@ -196,6 +196,7 @@ model BROADCOM3 BCM5717C 0x0020 BCM5717C 1000BASE-T media interface
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

View File

@ -134,6 +134,8 @@ typedef struct mii_softc mii_softc_t;
#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 */