diff options
Diffstat (limited to 'drivers/usb/host/xhci-mtk.c')
-rw-r--r-- | drivers/usb/host/xhci-mtk.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index c9ab6a44c34a..79959f17c38c 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -695,10 +695,24 @@ static int xhci_mtk_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int xhci_mtk_suspend(struct device *dev) +/* + * if ip sleep fails, and all clocks are disabled, access register will hang + * AHB bus, so stop polling roothubs to avoid regs access on bus suspend. + * and no need to check whether ip sleep failed or not; this will cause SPM + * to wake up system immediately after system suspend complete if ip sleep + * fails, it is what we wanted. + */ +static int __maybe_unused xhci_mtk_suspend(struct device *dev) { struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev); + struct usb_hcd *hcd = mtk->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + xhci_dbg(xhci, "%s: stop port polling\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); xhci_mtk_host_disable(mtk); xhci_mtk_phy_power_off(mtk); @@ -707,24 +721,29 @@ static int xhci_mtk_suspend(struct device *dev) return 0; } -static int xhci_mtk_resume(struct device *dev) +static int __maybe_unused xhci_mtk_resume(struct device *dev) { struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev); + struct usb_hcd *hcd = mtk->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); usb_wakeup_disable(mtk); xhci_mtk_clks_enable(mtk); xhci_mtk_phy_power_on(mtk); xhci_mtk_host_enable(mtk); + + xhci_dbg(xhci, "%s: restart port polling\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + usb_hcd_poll_rh_status(xhci->shared_hcd); return 0; } static const struct dev_pm_ops xhci_mtk_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(xhci_mtk_suspend, xhci_mtk_resume) }; -#define DEV_PM_OPS (&xhci_mtk_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif /* CONFIG_PM */ +#define DEV_PM_OPS IS_ENABLED(CONFIG_PM) ? &xhci_mtk_pm_ops : NULL #ifdef CONFIG_OF static const struct of_device_id mtk_xhci_of_match[] = { |