diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c2c71532d358..f9a1103c7ff2 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1949,8 +1949,18 @@ static int dwc3_resume(struct device *dev) int ret; /* Check if platform glue driver handling PM, if not then handle here */ - if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0)) + if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0)) { + /* + * If the core was in host mode during suspend, then set the + * runtime PM state as active to reflect actual state of device + * which is now out of LPM. This allows runtime_suspend later. + */ + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && + dwc->host_poweroff_in_pm_suspend) + goto runtime_set_active; + return 0; + } pinctrl_pm_select_default_state(dev); @@ -1958,6 +1968,7 @@ static int dwc3_resume(struct device *dev) if (ret) return ret; +runtime_set_active: pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e709da4cc67b..c08682fc63d1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1345,6 +1345,12 @@ struct dwc3 { unsigned int vbus_active:1; /* Indicate if software connect was issued by the usb_gadget_driver */ unsigned int softconnect:1; + /* + * If true, PM suspend allowed irrespective of host runtimePM state + * and core will power collapse. This also leads to reset-resume of + * connected devices on PM resume. + */ + bool host_poweroff_in_pm_suspend; }; #define INCRX_BURST_MODE 0 diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index f748cd49abbf..70732c21ca4c 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -43,7 +43,7 @@ out: int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[5]; + struct property_entry props[6]; struct platform_device *xhci; int ret, irq; struct resource *res; @@ -115,6 +115,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->revision <= DWC3_REVISION_300A) props[prop_idx++].name = "quirk-broken-port-ped"; + if (dwc->host_poweroff_in_pm_suspend) + props[prop_idx++].name = "host-poweroff-in-pm-suspend"; + if (prop_idx) { ret = platform_device_add_properties(xhci, props); if (ret) {