コード例 #1
0
ファイル: xhci-pci.c プロジェクト: hedongjie/m35x
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;
}
コード例 #2
0
ファイル: xhci-plat.c プロジェクト: AK101111/linux
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);
}
コード例 #3
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;
}
コード例 #4
0
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;
}
コード例 #5
0
ファイル: xhci-ubi32.c プロジェクト: patrick-ken/MyNet_N900
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;
}
コード例 #6
0
ファイル: xhci-histb.c プロジェクト: Lyude/linux
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);
}
コード例 #7
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;
}
コード例 #8
0
ファイル: xhci-plat.c プロジェクト: ReneNyffenegger/linux
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);
}
コード例 #9
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;

}