Index: sys/dev/mii/rgephy.c =================================================================== --- sys/dev/mii/rgephy.c +++ sys/dev/mii/rgephy.c @@ -39,6 +39,8 @@ * Driver for the RealTek 8169S/8110S/8211B/8211C internal 10/100/1000 PHY. */ +#include "opt_platform.h" + #include #include #include @@ -60,9 +62,25 @@ #include "miibus_if.h" +#ifdef FDT +#include +#include +#include +#include +#endif + #include #include +#define RGEPHY_QUIRK_PINE64_CONFREG 1 + +struct rgephy_softc { + mii_softc_t mii_sc; + device_t dev; + mii_contype_t contype; + int quirks; +}; + static int rgephy_probe(device_t); static int rgephy_attach(device_t); @@ -80,11 +98,14 @@ static driver_t rgephy_driver = { "rgephy", rgephy_methods, - sizeof(struct mii_softc) + sizeof(struct rgephy_softc) }; DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0); +#ifdef FDT +static void rgephy_fdt_get_config(struct rgephy_softc *); +#endif static int rgephy_service(struct mii_softc *, struct mii_data *, int); static void rgephy_status(struct mii_softc *); static int rgephy_mii_phy_auto(struct mii_softc *, int); @@ -106,6 +127,18 @@ rgephy_reset }; +#ifdef FDT +static void +rgephy_fdt_get_config(struct rgephy_softc *sc) +{ + mii_fdt_phy_config_t *cfg; + + cfg = mii_fdt_get_config(sc->dev); + sc->contype = cfg->con_type; + mii_fdt_free_config(cfg); +} +#endif + static int rgephy_probe(device_t dev) { @@ -116,15 +149,29 @@ static int rgephy_attach(device_t dev) { +#ifdef FDT + phandle_t root; +#endif + struct rgephy_softc *rsc; struct mii_softc *sc; u_int flags; - sc = device_get_softc(dev); + rsc = device_get_softc(dev); + rsc->dev = dev; + sc = &rsc->mii_sc; + flags = 0; if (mii_dev_mac_match(dev, "re")) flags |= MIIF_PHYPRIV0; else if (mii_dev_mac_match(dev, "ure")) flags |= MIIF_PHYPRIV1; +#ifdef FDT + rgephy_fdt_get_config(rsc); + if ((root = OF_finddevice("/")) != -1 && + ofw_bus_node_is_compatible(root, "pine64,pine64-plus") && + mii_contype_is_rgmii(rsc->contype)) + rsc->quirks |= RGEPHY_QUIRK_PINE64_CONFREG; +#endif mii_phy_dev_attach(dev, flags, &rgephy_funcs, 0); /* RTL8169S do not report auto-sense; add manually. */ @@ -523,8 +570,11 @@ static void rgephy_reset(struct mii_softc *sc) { + struct rgephy_softc *rsc; + int confreg; uint16_t pcr, ssr; + rsc = (struct rgephy_softc *)sc; switch (sc->mii_mpd_rev) { case RGEPHY_8211F: pcr = PHY_READ(sc, RGEPHY_F_MII_PCR1); @@ -556,6 +606,21 @@ mii_phy_reset(sc); DELAY(1000); + /* + * This sequence was obtained from Pine64 engineering; we need to + * ensure that TXD/RXD are disabled and some magic undocumented + * bits in the CONFREG register need to be flipped. + */ + if (rsc->quirks & RGEPHY_QUIRK_PINE64_CONFREG) { + PHY_WRITE(sc, RGEPHY_E_PAGSEL, 0x7); + PHY_WRITE(sc, RGEPHY_E_EPAGSR, 0xa4); + confreg = PHY_READ(sc, RGEPHY_E_CONFREG); + confreg &= ~(RGEPHY_E_CONFREG_TXD | RGEPHY_E_CONFREG_RXD); + confreg |= RGEPHY_E_CONFREG_MAGIC; + PHY_WRITE(sc, RGEPHY_E_CONFREG, confreg); + + PHY_WRITE(sc, RGEPHY_E_PAGSEL, 0); + } rgephy_load_dspcode(sc); } Index: sys/dev/mii/rgephyreg.h =================================================================== --- sys/dev/mii/rgephyreg.h +++ sys/dev/mii/rgephyreg.h @@ -39,6 +39,7 @@ #define RGEPHY_8211B 2 #define RGEPHY_8211C 3 +#define RGEPHY_8211E 5 #define RGEPHY_8211F 6 /* @@ -168,6 +169,14 @@ #define RGEPHY_SSR_ALDPS 0x0008 /* RTL8211C(L) only */ #define RGEPHY_SSR_JABBER 0x0001 /* Jabber */ +/* RTL8211E */ +#define RGEPHY_E_CONFREG 0x1C /* Configuration register */ +#define RGEPHY_E_CONFREG_TXD 0x0002 /* TXD Enabled */ +#define RGEPHY_E_CONFREG_RXD 0x0004 /* RXD Enabled */ +#define RGEPHY_E_CONFREG_MAGIC 0xb400 /* Undocumented */ +#define RGEPHY_E_EPAGSR 0x1E /* Extension page select register */ +#define RGEPHY_E_PAGSEL 0x1F /* Page select register */ + /* RTL8211F */ #define RGEPHY_F_MII_PCR1 0x18 /* PHY Specific control register 1 */ #define RGEPHY_F_PCR1_MDI_MM 0x0200 /* MDI / MDIX Manual Mode */