From: Uwe Stuehler Subject: support Marvell 88E151x RGMII delay timing modes in eephy(4) To: tech@openbsd.org Date: Thu, 11 Jan 2024 14:22:41 +0100 The following change, originally from stsp@, adds initial support for platforms which require Rx and/or Tx delays between MAC and PHY in RGMII mode (as per section "2.4.2 RGMII" in the datasheet.) I don't have access to a platform which requires this but I tested it on an Intel Elkhart Lake machine though where it had no effect. Does anyone know a platform which needs this, or should this go in as an improvement anyway? --- sys/dev/mii/eephy.c | 44 +++++++++++++++++++++++++++++++++++++----- sys/dev/mii/eephyreg.h | 7 +++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/sys/dev/mii/eephy.c b/sys/dev/mii/eephy.c index 049edb92021..c99bac094dd 100644 --- a/sys/dev/mii/eephy.c +++ b/sys/dev/mii/eephy.c @@ -57,6 +57,7 @@ int eephy_match(struct device *, void *, void *); void eephy_attach(struct device *, struct device *, void *); +int eephy_set_delay(struct mii_softc *); const struct cfattach eephy_ca = { sizeof (struct mii_softc), eephy_match, eephy_attach, mii_phy_detach @@ -213,6 +214,8 @@ eephy_attach(struct device *parent, struct device *self, void *aux) PHY_WRITE(sc, E1000_EADR, page); } + eephy_set_delay(sc); + PHY_RESET(sc); sc->mii_capabilities = PHY_READ(sc, E1000_SR) & ma->mii_capmask; @@ -315,6 +318,11 @@ eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmcr; + /* + * If autonegotiation is not enabled, we need a + * software reset for the settings to take effect. + */ + int sw_reset = (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO); if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0) return (ENXIO); @@ -347,11 +355,10 @@ eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) mii_phy_setmedia(sc); - /* - * If autonegotiation is not enabled, we need a - * software reset for the settings to take effect. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (eephy_set_delay(sc)) + sw_reset = 1; + + if (sw_reset) { bmcr = PHY_READ(sc, E1000_CR); PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_RESET); } @@ -381,6 +388,33 @@ eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); } +int +eephy_set_delay(struct mii_softc *sc) +{ + if (sc->mii_model == MII_MODEL_MARVELL_E1512 && + (sc->mii_flags & MIIF_SETDELAY)) { + int page, reg; + + page = PHY_READ(sc, E1000_EADR); + PHY_WRITE(sc, E1000_EADR, 2); + + reg = PHY_READ(sc, E1000_MSCR2); + reg &= ~E1000_MSCR2_DELAY_MASK; + if (sc->mii_flags & MIIF_RXID) + reg |= E1000_MSCR2_RXDELAY; + if (sc->mii_flags & MIIF_TXID) + reg |= E1000_MSCR2_TXDELAY; + + PHY_WRITE(sc, E1000_MSCR2, reg); + PHY_WRITE(sc, E1000_EADR, page); + + /* Indicate software reset needed. */ + return 1; + } + + return 0; +} + void eephy_status(struct mii_softc *sc) { diff --git a/sys/dev/mii/eephyreg.h b/sys/dev/mii/eephyreg.h index 4113791be61..7ac33885e27 100644 --- a/sys/dev/mii/eephyreg.h +++ b/sys/dev/mii/eephyreg.h @@ -337,3 +337,10 @@ #define E1000_GCR1_MODE_RGMII_100FX 0x0003 #define E1000_GCR1_MODE_RGMII_TO_SGMII 0x0004 #define E1000_GCR1_MODE_UNSET 0x0007 + +/* The following register is found only on the 88E151x Alaska PHY */ +/* Page 2 */ +#define E1000_MSCR2 0x15 /* MAC-Specific Control Register 2 */ +#define E1000_MSCR2_RXDELAY 0x20 +#define E1000_MSCR2_TXDELAY 0x10 +#define E1000_MSCR2_DELAY_MASK 0x30 -- 2.43.0