Index: sys/dev/usb/controller/dwc3.h =================================================================== --- sys/dev/usb/controller/dwc3.h +++ sys/dev/usb/controller/dwc3.h @@ -59,6 +59,8 @@ #define DWC3_GBUSERRADDRHI 0xc134 #define DWC3_GPRTBIMAPLO 0xc138 #define DWC3_GHWPARAMS0 0xc140 +#define DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE 0x2 +#define DWC3_GHWPARAMS0_MODE_MASK 0x3 #define DWC3_GHWPARAMS1 0xc144 #define DWC3_GHWPARAMS2 0xc148 #define DWC3_GHWPARAMS3 0xc14C @@ -93,6 +95,7 @@ #define DWC3_GUSB3PIPECTL0_PHYSOFTRST (1 << 31) #define DWC3_GUSB3PIPECTL0_DISRXDETINP3 (1 << 28) #define DWC3_GUSB3PIPECTL0_DELAYP1TRANS (1 << 18) +#define DWC3_GUSB3PIPECTL0_SUSPENDUSB3 (1 << 17) #define DWC3_GTXFIFOSIZ(x) (0xc300 + 0x4 * (x)) #define DWC3_GRXFIFOSIZ(x) (0xc380 + 0x4 * (x)) Index: sys/dev/usb/controller/dwc3.c =================================================================== --- sys/dev/usb/controller/dwc3.c +++ sys/dev/usb/controller/dwc3.c @@ -79,6 +79,8 @@ phandle_t node; phy_t usb2_phy; phy_t usb3_phy; + uint32_t snpsid; + uint32_t hwparams[9]; }; #define DWC3_WRITE(_sc, _off, _val) \ @@ -181,10 +183,16 @@ phy2 = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); phy2 |= DWC3_GUSB2PHYCFG0_PHYSOFTRST; + if ((sc->hwparams[0] & DWC3_GHWPARAMS0_MODE_MASK) == + DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) + phy2 &= ~DWC3_GUSB2PHYCFG0_SUSPENDUSB20; DWC3_WRITE(sc, DWC3_GUSB2PHYCFG0, phy2); phy3 = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); phy3 |= DWC3_GUSB3PIPECTL0_PHYSOFTRST; + if ((sc->hwparams[0] & DWC3_GHWPARAMS0_MODE_MASK) == + DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) + phy3 &= ~DWC3_GUSB3PIPECTL0_SUSPENDUSB3; DWC3_WRITE(sc, DWC3_GUSB3PIPECTL0, phy3); DELAY(1000); @@ -249,6 +257,7 @@ static void snps_dwc3_do_quirks(struct snps_dwc3_softc *sc) { + struct xhci_softc *xsc; uint32_t reg; reg = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); @@ -258,7 +267,8 @@ reg |= DWC3_GUSB2PHYCFG0_U2_FREECLK_EXISTS; if (device_has_property(sc->dev, "snps,dis_u2_susphy_quirk")) reg &= ~DWC3_GUSB2PHYCFG0_SUSPENDUSB20; - else + else if ((sc->hwparams[0] & DWC3_GHWPARAMS0_MODE_MASK) == + DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) reg |= DWC3_GUSB2PHYCFG0_SUSPENDUSB20; if (device_has_property(sc->dev, "snps,dis_enblslpm_quirk")) reg &= ~DWC3_GUSB2PHYCFG0_ENBLSLPM; @@ -276,7 +286,41 @@ reg &= ~DWC3_GUSB3PIPECTL0_DELAYP1TRANS; if (device_has_property(sc->dev, "snps,dis_rxdet_inp3_quirk")) reg |= DWC3_GUSB3PIPECTL0_DISRXDETINP3; + if (device_has_property(sc->dev, "snps,dis_u3_susphy_quirk")) + reg &= ~DWC3_GUSB3PIPECTL0_SUSPENDUSB3; + else if ((sc->hwparams[0] & DWC3_GHWPARAMS0_MODE_MASK) == + DWC3_GHWPARAMS0_MODE_DUALROLEDEVICE) + reg |= DWC3_GUSB3PIPECTL0_SUSPENDUSB3; DWC3_WRITE(sc, DWC3_GUSB3PIPECTL0, reg); + + /* Port Disable does not work on <= 3.00a. Disable PORT_PED. */ + if ((sc->snpsid & 0xffff) <= 0x300a) { + xsc = &sc->sc; + xsc->sc_quirks |= XHCI_QUIRK_DISABLE_PORT_PED; + } +} + +static void +snps_swc3_get_ctrlparams(struct snps_dwc3_softc *sc) +{ + const bus_size_t offs[] = { + DWC3_GHWPARAMS0, DWC3_GHWPARAMS1, DWC3_GHWPARAMS2, DWC3_GHWPARAMS3, + DWC3_GHWPARAMS4, DWC3_GHWPARAMS5, DWC3_GHWPARAMS6, DWC3_GHWPARAMS7, + DWC3_GHWPARAMS8, + }; + int i; + + sc->snpsid = DWC3_READ(sc, DWC3_GSNPSID); + if (bootverbose) + device_printf(sc->dev, "snps id: %#012x\n", sc->snpsid); + for (i = 0; i < nitems(sc->hwparams) && i < nitems(offs); i++) { + sc->hwparams[i] = DWC3_READ(sc, offs[i]); +#ifdef DWC3_DEBUG + if (bootverbose) + device_printf(sc->dev, "hwparams[%d]: %#012x\n", + i, sc->hwparams[i]); +#endif + } } static int @@ -326,8 +370,7 @@ sc->bst = rman_get_bustag(sc->mem_res); sc->bsh = rman_get_bushandle(sc->mem_res); - if (bootverbose) - device_printf(dev, "snps id: %x\n", DWC3_READ(sc, DWC3_GSNPSID)); + snps_swc3_get_ctrlparams(sc); /* Get the phys */ sc->node = ofw_bus_get_node(dev);