Loading drivers/usb/dwc3/core.c +2 −1 Original line number Diff line number Diff line Loading @@ -2005,7 +2005,8 @@ static int dwc3_resume(struct device *dev) * 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) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && pm_runtime_status_suspended(dev)) pm_runtime_resume(dev); return 0; Loading drivers/usb/dwc3/core.h +6 −4 Original line number Diff line number Diff line Loading @@ -1387,11 +1387,13 @@ struct dwc3 { /* 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. * If true, PM suspend/freeze allowed irrespective of host runtimePM * state. In PM suspend/resume case, core will stay powered and * connected devices will just be suspended/resumed. * In hibernation, core will power collapse and connected devices will * reset-resume on PM restore. */ bool host_poweroff_in_pm_suspend; bool ignore_wakeup_src_in_hostmode; int retries_on_error; u32 gen2_tx_de_emph; u32 gen2_tx_de_emph1; Loading drivers/usb/dwc3/dwc3-msm.c +85 −19 Original line number Diff line number Diff line Loading @@ -2851,7 +2851,8 @@ static int dwc3_msm_update_bus_bw(struct dwc3_msm *mdwc, enum bus_vote bv) return ret; } static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, bool enable_wakeup) { int ret; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); Loading Loading @@ -2944,7 +2945,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) ((mdwc->hs_phy->flags & (PHY_HSFS_MODE | PHY_LS_MODE)) && !dwc3_msm_is_superspeed(mdwc))); can_suspend_ssphy = dwc->maximum_speed >= USB_SPEED_SUPER && (!mdwc->use_pwr_event_for_wakeup || no_active_ss); (!mdwc->use_pwr_event_for_wakeup || no_active_ss || !enable_wakeup); /* Suspend SS PHY */ if (can_suspend_ssphy) { if (mdwc->in_host_mode) { Loading Loading @@ -3015,7 +3017,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in * case of host bus suspend and device bus suspend. */ if (!(mdwc->lpm_flags & MDWC3_POWER_COLLAPSE)) { if (!(mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) && enable_wakeup) { if (mdwc->use_pdc_interrupts) { enable_usb_pdc_interrupt(mdwc, true); } else { Loading Loading @@ -4446,6 +4448,12 @@ static int dwc3_msm_probe(struct platform_device *pdev) goto put_dwc3; } if (of_property_read_bool(node, "qcom,ignore-wakeup-src-in-hostmode")) { dwc->ignore_wakeup_src_in_hostmode = true; dev_dbg(mdwc->dev, "%s: Allow system suspend irrespective of runtime suspend\n", __func__); } /* * On platforms with SS PHY that do not support ss_phy_irq for wakeup * events, use pwr_event_irq for wakeup events in superspeed mode. Loading Loading @@ -4474,12 +4482,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->pm_qos_latency = 0; } if (of_property_read_bool(node, "qcom,host-poweroff-in-pm-suspend")) { dwc->host_poweroff_in_pm_suspend = true; dev_dbg(mdwc->dev, "%s: Core power collapse on host PM suspend\n", __func__); } mutex_init(&mdwc->suspend_resume_mutex); mdwc->ss_redriver_node = of_parse_phandle(node, "ssusb_redriver", 0); Loading Loading @@ -5302,7 +5304,7 @@ static int dwc3_msm_pm_suspend(struct device *dev) * Check if pm_suspend can proceed irrespective of runtimePM state of * host. */ if (!dwc->host_poweroff_in_pm_suspend || !mdwc->in_host_mode) { if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { if (!atomic_read(&dwc->in_lpm)) { dev_err(mdwc->dev, "Abort PM suspend!! (USB is outside LPM)\n"); return -EBUSY; Loading @@ -5313,6 +5315,67 @@ static int dwc3_msm_pm_suspend(struct device *dev) return 0; } /* Wakeup not required for automotive/telematics platform host mode */ ret = dwc3_msm_suspend(mdwc, false, false); if (!ret) atomic_set(&mdwc->pm_suspended, 1); return ret; } static int dwc3_msm_pm_resume(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM resume\n"); dbg_event(0xFF, "PM Res", 0); atomic_set(&mdwc->pm_suspended, 0); if (!mdwc->in_host_mode) { /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } /* Resume dwc to avoid unclocked access by xhci_plat_resume */ if (pm_runtime_status_suspended(dev)) pm_runtime_resume(dev); else dwc3_msm_resume(mdwc); /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } static int dwc3_msm_pm_freeze(struct device *dev) { int ret = 0; struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM freeze\n"); dbg_event(0xFF, "PM Freeze", 0); /* * Check if pm_freeze can proceed irrespective of runtimePM state of * host. */ if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { if (!atomic_read(&dwc->in_lpm)) { dev_err(mdwc->dev, "Abort PM freeze!! (USB is outside LPM)\n"); return -EBUSY; } atomic_set(&mdwc->pm_suspended, 1); return 0; } /* * PHYs also need to be power collapsed, so call notify_disconnect * before suspend to ensure it. Loading @@ -5325,21 +5388,22 @@ static int dwc3_msm_pm_suspend(struct device *dev) /* * Power collapse the core. Hence call dwc3_msm_suspend with * 'force_power_collapse' set to 'true'. * Wakeup not required for automotive/telematics platform host mode. */ ret = dwc3_msm_suspend(mdwc, true); ret = dwc3_msm_suspend(mdwc, true, false); if (!ret) atomic_set(&mdwc->pm_suspended, 1); return ret; } static int dwc3_msm_pm_resume(struct device *dev) static int dwc3_msm_pm_restore(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM resume\n"); dbg_event(0xFF, "PM Res", 0); dev_dbg(dev, "dwc3-msm PM restore\n"); dbg_event(0xFF, "PM Restore", 0); atomic_set(&mdwc->pm_suspended, 0); Loading @@ -5352,9 +5416,6 @@ static int dwc3_msm_pm_resume(struct device *dev) /* Resume dwc to avoid unclocked access by xhci_plat_resume */ dwc3_msm_resume(mdwc); pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); /* Restore PHY flags if hibernated in host mode */ mdwc->hs_phy->flags |= PHY_HOST_MODE; Loading Loading @@ -5392,7 +5453,7 @@ static int dwc3_msm_runtime_suspend(struct device *dev) dev_dbg(dev, "DWC3-msm runtime suspend\n"); dbg_event(0xFF, "RT Sus", 0); return dwc3_msm_suspend(mdwc, false); return dwc3_msm_suspend(mdwc, false, true); } static int dwc3_msm_runtime_resume(struct device *dev) Loading @@ -5408,7 +5469,12 @@ static int dwc3_msm_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops dwc3_msm_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_msm_pm_suspend, dwc3_msm_pm_resume) .suspend = dwc3_msm_pm_suspend, .resume = dwc3_msm_pm_resume, .freeze = dwc3_msm_pm_freeze, .thaw = dwc3_msm_pm_restore, .poweroff = dwc3_msm_pm_suspend, .restore = dwc3_msm_pm_restore, SET_RUNTIME_PM_OPS(dwc3_msm_runtime_suspend, dwc3_msm_runtime_resume, dwc3_msm_runtime_idle) }; Loading drivers/usb/dwc3/host.c +2 −2 Original line number Diff line number Diff line Loading @@ -115,9 +115,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->revision <= DWC3_REVISION_300A) props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped"); if (dwc->host_poweroff_in_pm_suspend) if (dwc->ignore_wakeup_src_in_hostmode) props[prop_idx++] = PROPERTY_ENTRY_BOOL("host-poweroff-in-pm-suspend"); PROPERTY_ENTRY_BOOL("ignore-wakeup-src-in-hostmode"); if (prop_idx) { ret = platform_device_add_properties(xhci, props); Loading drivers/usb/host/xhci-plat.c +66 −23 Original line number Diff line number Diff line Loading @@ -391,24 +391,7 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } static int __maybe_unused xhci_plat_runtime_idle(struct device *dev) { /* * When pm_runtime_put_autosuspend() is called on this device, * after this idle callback returns the PM core will schedule the * autosuspend if there is any remaining time until expiry. However, * when reaching this point because the child_count becomes 0, the * core does not honor autosuspend in that case and results in * idle/suspend happening immediately. In order to have a delay * before suspend we have to call pm_runtime_autosuspend() manually. */ pm_runtime_mark_last_busy(dev); pm_runtime_autosuspend(dev); return -EBUSY; } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) static int xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); Loading @@ -416,9 +399,10 @@ static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) if (!xhci) return 0; dev_dbg(dev, "xhci-plat runtime suspend\n"); dev_dbg(dev, "xhci-plat PM suspend\n"); return xhci_suspend(xhci, true); /* Disable wakeup capability */ return xhci_suspend(xhci, false); } static int xhci_plat_resume(struct device *dev) Loading @@ -436,13 +420,68 @@ static int xhci_plat_resume(struct device *dev) if (ret) return ret; if (pm_runtime_status_suspended(dev)) ret = pm_runtime_resume(dev); else ret = xhci_resume(xhci, false); if (ret) dev_err(dev, "failed to resume xhci-plat (%d)\n", ret); return ret; } static int xhci_plat_restore(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; if (!xhci) return 0; dev_dbg(dev, "xhci-plat PM restore\n"); ret = xhci_priv_resume_quirk(hcd); if (ret) return ret; /* resume from hibernation/power-collapse */ ret = xhci_resume(xhci, true); return ret; } static int __maybe_unused xhci_plat_runtime_idle(struct device *dev) { /* * When pm_runtime_put_autosuspend() is called on this device, * after this idle callback returns the PM core will schedule the * autosuspend if there is any remaining time until expiry. However, * when reaching this point because the child_count becomes 0, the * core does not honor autosuspend in that case and results in * idle/suspend happening immediately. In order to have a delay * before suspend we have to call pm_runtime_autosuspend() manually. */ pm_runtime_mark_last_busy(dev); pm_runtime_autosuspend(dev); return -EBUSY; } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); if (!xhci) return 0; dev_dbg(dev, "xhci-plat runtime suspend\n"); return xhci_suspend(xhci, true); } static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); Loading @@ -465,8 +504,12 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) } static const struct dev_pm_ops xhci_plat_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(NULL, xhci_plat_resume) .suspend = xhci_plat_suspend, .resume = xhci_plat_resume, .freeze = xhci_plat_suspend, .thaw = xhci_plat_restore, .poweroff = xhci_plat_suspend, .restore = xhci_plat_restore, SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume, xhci_plat_runtime_idle) Loading Loading
drivers/usb/dwc3/core.c +2 −1 Original line number Diff line number Diff line Loading @@ -2005,7 +2005,8 @@ static int dwc3_resume(struct device *dev) * 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) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && pm_runtime_status_suspended(dev)) pm_runtime_resume(dev); return 0; Loading
drivers/usb/dwc3/core.h +6 −4 Original line number Diff line number Diff line Loading @@ -1387,11 +1387,13 @@ struct dwc3 { /* 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. * If true, PM suspend/freeze allowed irrespective of host runtimePM * state. In PM suspend/resume case, core will stay powered and * connected devices will just be suspended/resumed. * In hibernation, core will power collapse and connected devices will * reset-resume on PM restore. */ bool host_poweroff_in_pm_suspend; bool ignore_wakeup_src_in_hostmode; int retries_on_error; u32 gen2_tx_de_emph; u32 gen2_tx_de_emph1; Loading
drivers/usb/dwc3/dwc3-msm.c +85 −19 Original line number Diff line number Diff line Loading @@ -2851,7 +2851,8 @@ static int dwc3_msm_update_bus_bw(struct dwc3_msm *mdwc, enum bus_vote bv) return ret; } static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, bool enable_wakeup) { int ret; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); Loading Loading @@ -2944,7 +2945,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) ((mdwc->hs_phy->flags & (PHY_HSFS_MODE | PHY_LS_MODE)) && !dwc3_msm_is_superspeed(mdwc))); can_suspend_ssphy = dwc->maximum_speed >= USB_SPEED_SUPER && (!mdwc->use_pwr_event_for_wakeup || no_active_ss); (!mdwc->use_pwr_event_for_wakeup || no_active_ss || !enable_wakeup); /* Suspend SS PHY */ if (can_suspend_ssphy) { if (mdwc->in_host_mode) { Loading Loading @@ -3015,7 +3017,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse) * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in * case of host bus suspend and device bus suspend. */ if (!(mdwc->lpm_flags & MDWC3_POWER_COLLAPSE)) { if (!(mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) && enable_wakeup) { if (mdwc->use_pdc_interrupts) { enable_usb_pdc_interrupt(mdwc, true); } else { Loading Loading @@ -4446,6 +4448,12 @@ static int dwc3_msm_probe(struct platform_device *pdev) goto put_dwc3; } if (of_property_read_bool(node, "qcom,ignore-wakeup-src-in-hostmode")) { dwc->ignore_wakeup_src_in_hostmode = true; dev_dbg(mdwc->dev, "%s: Allow system suspend irrespective of runtime suspend\n", __func__); } /* * On platforms with SS PHY that do not support ss_phy_irq for wakeup * events, use pwr_event_irq for wakeup events in superspeed mode. Loading Loading @@ -4474,12 +4482,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->pm_qos_latency = 0; } if (of_property_read_bool(node, "qcom,host-poweroff-in-pm-suspend")) { dwc->host_poweroff_in_pm_suspend = true; dev_dbg(mdwc->dev, "%s: Core power collapse on host PM suspend\n", __func__); } mutex_init(&mdwc->suspend_resume_mutex); mdwc->ss_redriver_node = of_parse_phandle(node, "ssusb_redriver", 0); Loading Loading @@ -5302,7 +5304,7 @@ static int dwc3_msm_pm_suspend(struct device *dev) * Check if pm_suspend can proceed irrespective of runtimePM state of * host. */ if (!dwc->host_poweroff_in_pm_suspend || !mdwc->in_host_mode) { if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { if (!atomic_read(&dwc->in_lpm)) { dev_err(mdwc->dev, "Abort PM suspend!! (USB is outside LPM)\n"); return -EBUSY; Loading @@ -5313,6 +5315,67 @@ static int dwc3_msm_pm_suspend(struct device *dev) return 0; } /* Wakeup not required for automotive/telematics platform host mode */ ret = dwc3_msm_suspend(mdwc, false, false); if (!ret) atomic_set(&mdwc->pm_suspended, 1); return ret; } static int dwc3_msm_pm_resume(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM resume\n"); dbg_event(0xFF, "PM Res", 0); atomic_set(&mdwc->pm_suspended, 0); if (!mdwc->in_host_mode) { /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } /* Resume dwc to avoid unclocked access by xhci_plat_resume */ if (pm_runtime_status_suspended(dev)) pm_runtime_resume(dev); else dwc3_msm_resume(mdwc); /* kick in otg state machine */ queue_work(mdwc->dwc3_wq, &mdwc->resume_work); return 0; } static int dwc3_msm_pm_freeze(struct device *dev) { int ret = 0; struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM freeze\n"); dbg_event(0xFF, "PM Freeze", 0); /* * Check if pm_freeze can proceed irrespective of runtimePM state of * host. */ if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) { if (!atomic_read(&dwc->in_lpm)) { dev_err(mdwc->dev, "Abort PM freeze!! (USB is outside LPM)\n"); return -EBUSY; } atomic_set(&mdwc->pm_suspended, 1); return 0; } /* * PHYs also need to be power collapsed, so call notify_disconnect * before suspend to ensure it. Loading @@ -5325,21 +5388,22 @@ static int dwc3_msm_pm_suspend(struct device *dev) /* * Power collapse the core. Hence call dwc3_msm_suspend with * 'force_power_collapse' set to 'true'. * Wakeup not required for automotive/telematics platform host mode. */ ret = dwc3_msm_suspend(mdwc, true); ret = dwc3_msm_suspend(mdwc, true, false); if (!ret) atomic_set(&mdwc->pm_suspended, 1); return ret; } static int dwc3_msm_pm_resume(struct device *dev) static int dwc3_msm_pm_restore(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(dev, "dwc3-msm PM resume\n"); dbg_event(0xFF, "PM Res", 0); dev_dbg(dev, "dwc3-msm PM restore\n"); dbg_event(0xFF, "PM Restore", 0); atomic_set(&mdwc->pm_suspended, 0); Loading @@ -5352,9 +5416,6 @@ static int dwc3_msm_pm_resume(struct device *dev) /* Resume dwc to avoid unclocked access by xhci_plat_resume */ dwc3_msm_resume(mdwc); pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); /* Restore PHY flags if hibernated in host mode */ mdwc->hs_phy->flags |= PHY_HOST_MODE; Loading Loading @@ -5392,7 +5453,7 @@ static int dwc3_msm_runtime_suspend(struct device *dev) dev_dbg(dev, "DWC3-msm runtime suspend\n"); dbg_event(0xFF, "RT Sus", 0); return dwc3_msm_suspend(mdwc, false); return dwc3_msm_suspend(mdwc, false, true); } static int dwc3_msm_runtime_resume(struct device *dev) Loading @@ -5408,7 +5469,12 @@ static int dwc3_msm_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops dwc3_msm_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_msm_pm_suspend, dwc3_msm_pm_resume) .suspend = dwc3_msm_pm_suspend, .resume = dwc3_msm_pm_resume, .freeze = dwc3_msm_pm_freeze, .thaw = dwc3_msm_pm_restore, .poweroff = dwc3_msm_pm_suspend, .restore = dwc3_msm_pm_restore, SET_RUNTIME_PM_OPS(dwc3_msm_runtime_suspend, dwc3_msm_runtime_resume, dwc3_msm_runtime_idle) }; Loading
drivers/usb/dwc3/host.c +2 −2 Original line number Diff line number Diff line Loading @@ -115,9 +115,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->revision <= DWC3_REVISION_300A) props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped"); if (dwc->host_poweroff_in_pm_suspend) if (dwc->ignore_wakeup_src_in_hostmode) props[prop_idx++] = PROPERTY_ENTRY_BOOL("host-poweroff-in-pm-suspend"); PROPERTY_ENTRY_BOOL("ignore-wakeup-src-in-hostmode"); if (prop_idx) { ret = platform_device_add_properties(xhci, props); Loading
drivers/usb/host/xhci-plat.c +66 −23 Original line number Diff line number Diff line Loading @@ -391,24 +391,7 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } static int __maybe_unused xhci_plat_runtime_idle(struct device *dev) { /* * When pm_runtime_put_autosuspend() is called on this device, * after this idle callback returns the PM core will schedule the * autosuspend if there is any remaining time until expiry. However, * when reaching this point because the child_count becomes 0, the * core does not honor autosuspend in that case and results in * idle/suspend happening immediately. In order to have a delay * before suspend we have to call pm_runtime_autosuspend() manually. */ pm_runtime_mark_last_busy(dev); pm_runtime_autosuspend(dev); return -EBUSY; } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) static int xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); Loading @@ -416,9 +399,10 @@ static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) if (!xhci) return 0; dev_dbg(dev, "xhci-plat runtime suspend\n"); dev_dbg(dev, "xhci-plat PM suspend\n"); return xhci_suspend(xhci, true); /* Disable wakeup capability */ return xhci_suspend(xhci, false); } static int xhci_plat_resume(struct device *dev) Loading @@ -436,13 +420,68 @@ static int xhci_plat_resume(struct device *dev) if (ret) return ret; if (pm_runtime_status_suspended(dev)) ret = pm_runtime_resume(dev); else ret = xhci_resume(xhci, false); if (ret) dev_err(dev, "failed to resume xhci-plat (%d)\n", ret); return ret; } static int xhci_plat_restore(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; if (!xhci) return 0; dev_dbg(dev, "xhci-plat PM restore\n"); ret = xhci_priv_resume_quirk(hcd); if (ret) return ret; /* resume from hibernation/power-collapse */ ret = xhci_resume(xhci, true); return ret; } static int __maybe_unused xhci_plat_runtime_idle(struct device *dev) { /* * When pm_runtime_put_autosuspend() is called on this device, * after this idle callback returns the PM core will schedule the * autosuspend if there is any remaining time until expiry. However, * when reaching this point because the child_count becomes 0, the * core does not honor autosuspend in that case and results in * idle/suspend happening immediately. In order to have a delay * before suspend we have to call pm_runtime_autosuspend() manually. */ pm_runtime_mark_last_busy(dev); pm_runtime_autosuspend(dev); return -EBUSY; } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); if (!xhci) return 0; dev_dbg(dev, "xhci-plat runtime suspend\n"); return xhci_suspend(xhci, true); } static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); Loading @@ -465,8 +504,12 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) } static const struct dev_pm_ops xhci_plat_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(NULL, xhci_plat_resume) .suspend = xhci_plat_suspend, .resume = xhci_plat_resume, .freeze = xhci_plat_suspend, .thaw = xhci_plat_restore, .poweroff = xhci_plat_suspend, .restore = xhci_plat_restore, SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume, xhci_plat_runtime_idle) Loading