diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index e6e8bed11aea..c8018cd8e4fe 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1568,7 +1568,21 @@ retry: t2 &= ~PORT_PLS_MASK; t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); + } else if ((xhci->quirks & XHCI_U2_BROKEN_SUSPEND) && + (hcd->speed < HCD_USB3) && + (t1 & PORT_PLS_MASK) == XDEV_U3) { + /* + * Rockchip SNPS xHC 3.0 set USB 2.0 PHY enter + * suspend mode from DWC3 core if the suspend + * conditions are valid. In this case, it need + * to set the bus_suspended bit for USB 2.0, so + * that in xhci_bus_resume, it can set the xHC + * link state to XDEV_RESUME and send USB resume + * signal to USB 2.0 device. + */ + set_bit(port_index, &bus_state->bus_suspended); } + /* USB core sets remote wake mask for USB 3.0 hubs, * including the USB 3.0 roothub, but only if CONFIG_PM * is enabled, so also enable remote wake here. diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 09dceed14f82..688b968f1bdc 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -301,6 +301,10 @@ static int xhci_plat_probe(struct platform_device *pdev) "xhci-warm-reset-on-suspend")) xhci->quirks |= XHCI_WARM_RESET_ON_SUSPEND; + if (device_property_read_bool(tmpdev, + "xhci-u2-broken-suspend")) + xhci->quirks |= XHCI_U2_BROKEN_SUSPEND; + device_property_read_u32(tmpdev, "imod-interval-ns", &xhci->imod_interval); } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 56a618616323..301217641765 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1889,6 +1889,7 @@ struct xhci_hcd { #define XHCI_DIS_AUTOSUSPEND BIT_ULL(37) #define XHCI_DISABLE_SPARSE BIT_ULL(38) #define XHCI_WARM_RESET_ON_SUSPEND BIT_ULL(39) +#define XHCI_U2_BROKEN_SUSPEND BIT_ULL(40) unsigned int num_active_eps; unsigned int limit_active_eps;