static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval = 0; /* The BIOS on systems with the Intel Panther Point chipset may or may * not support xHCI natively. That means that during system resume, it * may switch the ports back to EHCI so that users can use their * keyboard to select a kernel from GRUB after resume from hibernate. * * The BIOS is supposed to remember whether the OS had xHCI ports * enabled before resume, and switch the ports back to xHCI when the * BIOS/OS semaphore is written, but we all know we can't trust BIOS * writers. * * Unconditionally switch the ports back to xHCI after a system resume. * We can't tell whether the EHCI or xHCI controller will be resumed * first, so we have to do the port switchover in both drivers. Writing * a '1' to the port switchover registers should have no effect if the * port was already switched over. */ if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); retval = xhci_resume(xhci, hibernated); return retval; }
static int xhci_plat_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); return xhci_resume(xhci, 0); }
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval = 0; /* The BIOS on systems with the Intel Panther Point chipset may or may * not support xHCI natively. That means that during system resume, it * may switch the ports back to EHCI so that users can use their * keyboard to select a kernel from GRUB after resume from hibernate. * * The BIOS is supposed to remember whether the OS had xHCI ports * enabled before resume, and switch the ports back to xHCI when the * BIOS/OS semaphore is written, but we all know we can't trust BIOS * writers. * * Unconditionally switch the ports back to xHCI after a system resume. * It should not matter whether the EHCI or xHCI controller is * resumed first. It's enough to do the switchover in xHCI because * USB core won't notice anything as the hub driver doesn't start * running again until after all the devices (including both EHCI and * xHCI host controllers) have been resumed. */ if (pdev->vendor == PCI_VENDOR_ID_INTEL) usb_enable_intel_xhci_ports(pdev); if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(xhci); retval = xhci_resume(xhci, hibernated); return retval; }
static int exynos_xhci_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_xhci_hcd *exynos_xhci; struct usb_hcd *hcd; struct xhci_hcd *xhci; int retval = 0; dev_dbg(dev, "%s\n", __func__); exynos_xhci = dev_get_drvdata(dev); if (!exynos_xhci) return -EINVAL; hcd = exynos_xhci->hcd; if (!hcd) return -EINVAL; if (dev->power.is_suspended) { dev_dbg(dev, "xhci is system suspended\n"); return 0; } /* Userspace may try to access host when DRD is in B-Dev mode */ if (exynos_drd_try_get(pdev)) { dev_dbg(dev, "%s: cannot get DRD\n", __func__); return -EAGAIN; } pm_runtime_get_sync(exynos_xhci->dev->parent); /* * Parent device (DRD core) resumes before its child (xHCI). * Since we "get" DRD when it's already active, we need to * reconfigure PHY here, so PHY tuning took effect. */ if (exynos_xhci->core->ops->phy_set) exynos_xhci->core->ops->phy_set(exynos_xhci->core); if (exynos_xhci->core->ops->change_mode) exynos_xhci->core->ops->change_mode(exynos_xhci->core, true); if (exynos_xhci->core->ops->core_init) exynos_xhci->core->ops->core_init(exynos_xhci->core); xhci = hcd_to_xhci(hcd); retval = xhci_resume(xhci, 0); if (retval < 0) dev_err(dev, "%s: cannot start xHC\n", __func__); /* * In xhci_resume(), config values(AHB bus and los_bias) are intialized. * So after called xhci_resume(), set the config values again. */ if (exynos_xhci->core->ops->config) exynos_xhci->core->ops->config(exynos_xhci->core); return retval; }
static int ubi32_xhci_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int retval = 0; retval = xhci_resume(xhci, 0); return retval; }
static int __maybe_unused xhci_histb_resume(struct device *dev) { struct xhci_hcd_histb *histb = dev_get_drvdata(dev); struct usb_hcd *hcd = histb->hcd; struct xhci_hcd *xhci = hcd_to_xhci(hcd); if (!device_may_wakeup(dev)) xhci_histb_host_enable(histb); return xhci_resume(xhci, 0); }
static int exynos_xhci_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_xhci_hcd *exynos_xhci; struct usb_hcd *hcd; struct xhci_hcd *xhci; int retval = 0; #ifdef CONFIG_PM_RUNTIME dev_dbg(dev, "%s: usage_count = %d\n", __func__, atomic_read(&dev->power.usage_count)); #endif exynos_xhci = dev_get_drvdata(dev); if (!exynos_xhci) return -EINVAL; hcd = exynos_xhci->hcd; if (!hcd) return -EINVAL; if (exynos_drd_try_get(pdev)) { dev_err(dev, "%s: cannot get DRD\n", __func__); return -EAGAIN; } /* Wake up and initialize DRD core */ pm_runtime_get_sync(dev->parent); if (exynos_xhci->core->ops->change_mode) exynos_xhci->core->ops->change_mode(exynos_xhci->core, true); if (exynos_xhci->core->ops->core_init) exynos_xhci->core->ops->core_init(exynos_xhci->core); xhci = hcd_to_xhci(hcd); retval = xhci_resume(xhci, 0); if (retval < 0) dev_err(dev, "%s: cannot start xHC\n", __func__); /* * In xhci_resume(), config values(AHB bus and los_bias) are intialized. * So after called xhci_resume(), set the config values again. */ if (exynos_xhci->core->ops->config) exynos_xhci->core->ops->config(exynos_xhci->core); /* Update runtime PM status and clear runtime_error */ pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); return retval; }
static int __maybe_unused xhci_plat_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) clk_prepare_enable(xhci->clk); ret = xhci_priv_resume_quirk(hcd); if (ret) return ret; return xhci_resume(xhci, 0); }
/* dwc_hcd_suspend_common and dwc_hcd_resume_common are refer to * suspend_common and resume_common in usb core. * Because the usb core function just support PCI device. * So re-write them in here to support platform devices. */ static int dwc_hcd_suspend_common(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct usb_hcd *hcd = platform_get_drvdata(pdev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int retval = 0; u32 data = 0; if (!xhci) { dev_dbg(dev, "%s: host already stop!\n", __func__); return 0; } /* Root hub suspend should have stopped all downstream traffic, * and all bus master traffic. And done so for both the interface * and the stub usb_device (which we check here). But maybe it * didn't; writing sysfs power/state files ignores such rules... */ if (HCD_RH_RUNNING(hcd)) { dev_warn(dev, "Root hub is not suspended\n"); return -EBUSY; } if (hcd->shared_hcd) { hcd = hcd->shared_hcd; if (HCD_RH_RUNNING(hcd)) { dev_warn(dev, "Secondary root hub is not suspended\n"); return -EBUSY; } } if (!HCD_DEAD(hcd)) { /* Optimization: Don't suspend if a root-hub wakeup is * pending and it would cause the HCD to wake up anyway. */ if (HCD_WAKEUP_PENDING(hcd)) return -EBUSY; if (hcd->shared_hcd && HCD_WAKEUP_PENDING(hcd->shared_hcd)) return -EBUSY; if (hcd->state != HC_STATE_SUSPENDED || xhci->shared_hcd->state != HC_STATE_SUSPENDED) retval = -EINVAL; if (!retval) { /* The auto-resume is diabled by default. Need enable it * if there have valid connection. To ensure that when * device resumes, host does resume reflect within * 900 usec as in USB spec. */ if (if_usb_devices_connected(xhci) == 1) dwc_xhci_enable_phy_auto_resume( xhci->main_hcd, true); /* Ensure that suspend enable are set for * USB2 and USB3 PHY */ dwc_xhci_enable_phy_suspend(hcd, true); data = readl(hcd->regs + GCTL); data |= GCTL_GBL_HIBERNATION_EN; writel(data, hcd->regs + GCTL); dev_dbg(hcd->self.controller, "set xhci hibernation enable!\n"); retval = xhci_suspend(xhci); } /* Check again in case wakeup raced with pci_suspend */ if ((retval == 0 && HCD_WAKEUP_PENDING(hcd)) || (retval == 0 && hcd->shared_hcd && HCD_WAKEUP_PENDING(hcd->shared_hcd))) { xhci_resume(xhci, false); retval = -EBUSY; } if (retval) return retval; } synchronize_irq(dwc3_xhci.otg_irqnum); return retval; }