Index: sys/dev/usb/controller/dwc3.h =================================================================== --- sys/dev/usb/controller/dwc3.h +++ sys/dev/usb/controller/dwc3.h @@ -54,10 +54,13 @@ #define DWC3_GGPIO 0xc124 #define DWC3_GUID 0xc128 #define DWC3_GUCTL 0xc12C +#define DWC3_GUCTL_HOST_AUTO_RETRY (1 << 14) #define DWC3_GBUSERRADDRLO 0xc130 #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 @@ -92,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 @@ -80,6 +80,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) \ @@ -147,22 +149,33 @@ return (0); } -#if 0 +#ifdef DWC3_DEBUG static void -snsp_dwc3_dump_regs(struct snps_dwc3_softc *sc) +snsp_dwc3_dump_regs(struct snps_dwc3_softc *sc, const char *msg) { + struct xhci_softc *xsc; uint32_t reg; + if (!bootverbose) + return; + + device_printf(sc->dev, "%s: %s:\n", __func__, msg ? msg : ""); + reg = DWC3_READ(sc, DWC3_GCTL); - device_printf(sc->dev, "GCTL: %x\n", reg); + device_printf(sc->dev, "GCTL: %#012x\n", reg); + reg = DWC3_READ(sc, DWC3_GUCTL); + device_printf(sc->dev, "GUCTL: %#012x\n", reg); reg = DWC3_READ(sc, DWC3_GUCTL1); - device_printf(sc->dev, "GUCTL1: %x\n", reg); + device_printf(sc->dev, "GUCTL1: %#012x\n", reg); reg = DWC3_READ(sc, DWC3_GUSB2PHYCFG0); - device_printf(sc->dev, "GUSB2PHYCFG0: %x\n", reg); + device_printf(sc->dev, "GUSB2PHYCFG0: %#012x\n", reg); reg = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); - device_printf(sc->dev, "GUSB3PIPECTL0: %x\n", reg); + device_printf(sc->dev, "GUSB3PIPECTL0: %#012x\n", reg); reg = DWC3_READ(sc, DWC3_DCFG); - device_printf(sc->dev, "DCFG: %x\n", reg); + device_printf(sc->dev, "DCFG: %#012x\n", reg); + + xsc = &sc->sc; + device_printf(sc->dev, "xhci quirks: %#012x\n", xsc->sc_quirks); } #endif @@ -182,10 +195,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); @@ -210,6 +229,10 @@ reg &= ~DWC3_GCTL_PRTCAPDIR_MASK; reg |= DWC3_GCTL_PRTCAPDIR_HOST; DWC3_WRITE(sc, DWC3_GCTL, reg); + + reg = DWC3_READ(sc, DWC3_GUCTL); + reg |= DWC3_GUCTL_HOST_AUTO_RETRY; + DWC3_WRITE(sc, DWC3_GUCTL, reg); } static void @@ -241,6 +264,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); @@ -250,7 +274,8 @@ reg |= DWC3_GUSB2PHYCFG0_U2_FREECLK_EXISTS; if (OF_hasprop(sc->node, "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 (OF_hasprop(sc->node, "snps,dis_enblslpm_quirk")) reg &= ~DWC3_GUSB2PHYCFG0_ENBLSLPM; @@ -266,11 +291,21 @@ reg = DWC3_READ(sc, DWC3_GUSB3PIPECTL0); if (OF_hasprop(sc->node, "snps,dis-del-phy-power-chg-quirk")) - reg |= DWC3_GUSB3PIPECTL0_DELAYP1TRANS; + reg &= ~DWC3_GUSB3PIPECTL0_DELAYP1TRANS; if (OF_hasprop(sc->node, "snps,dis_rxdet_inp3_quirk")) reg |= DWC3_GUSB3PIPECTL0_DISRXDETINP3; + if (device_has_property(sc->dev, "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 int @@ -296,6 +331,29 @@ return (BUS_PROBE_DEFAULT); } +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 snps_dwc3_attach(device_t dev) { @@ -314,8 +372,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 */ phy_get_by_ofw_name(dev, sc->node, "usb2-phy", &sc->usb2_phy); @@ -325,10 +382,13 @@ snps_dwc3_configure_host(sc); snps_dwc3_configure_phy(sc); snps_dwc3_do_quirks(sc); -#if 0 - snsp_dwc3_dump_regs(sc); +#ifdef DWC3_DEBUG + snsp_dwc3_dump_regs(sc, "Pre XHCI init"); #endif snps_dwc3_attach_xhci(dev); +#ifdef DWC3_DEBUG + snsp_dwc3_dump_regs(sc, "Post XHCI init"); +#endif return (0); }