diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 44ed85a8da73..57c94c60cecc 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1676,7 +1676,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 bd62f03523f1..f76cdb306ea8 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -363,6 +363,10 @@ static int xhci_plat_probe(struct platform_device *pdev) if (device_property_read_bool(tmpdev, "quirk-skip-phy-init")) xhci->quirks |= XHCI_SKIP_PHY_INIT; + 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 111dc5ff3f0d..16cc027d2560 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1906,6 +1906,7 @@ struct xhci_hcd { #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) +#define XHCI_U2_BROKEN_SUSPEND BIT_ULL(43) unsigned int num_active_eps; unsigned int limit_active_eps;