Beispiel #1
0
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
	int			ret;

	/*
	 * Systems with the TI redriver that loses port status change events
	 * need to have the registers polled during D3, so avoid D3cold.
	 */
	if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
		pci_d3cold_disable(pdev);

	if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
		xhci_pme_quirk(hcd);

	if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
		xhci_ssic_port_unused_quirk(hcd, true);

	ret = xhci_suspend(xhci, do_wakeup);
	if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
		xhci_ssic_port_unused_quirk(hcd, false);

	return ret;
}
Beispiel #2
0
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);

	return xhci_suspend(xhci, true);
}
Beispiel #3
0
static int xhci_plat_suspend(struct device *dev)
{
	struct usb_hcd	*hcd = dev_get_drvdata(dev);
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);

	return xhci_suspend(xhci);
}
Beispiel #4
0
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int	retval = 0;

	if (hcd->state != HC_STATE_SUSPENDED ||
			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
		return -EINVAL;

	retval = xhci_suspend(xhci);

	return retval;
}
Beispiel #5
0
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);

	/*
	 * Systems with the TI redriver that loses port status change events
	 * need to have the registers polled during D3, so avoid D3cold.
	 */
	if (xhci_compliance_mode_recovery_timer_quirk_check())
		pdev->no_d3cold = true;

	return xhci_suspend(xhci);
}
Beispiel #6
0
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);

	/*
	 * Systems with the TI redriver that loses port status change events
	 * need to have the registers polled during D3, so avoid D3cold.
	 */
	if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
		pdev->no_d3cold = true;

	return xhci_suspend(xhci);
}
Beispiel #7
0
static int ubi32_xhci_drv_suspend(struct device *dev)
{
    struct usb_hcd *hcd = dev_get_drvdata(dev);
    struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
    int	retval = 0;

    if (hcd->state != HC_STATE_SUSPENDED ||
            xhci->shared_hcd->state != HC_STATE_SUSPENDED)
        return -EINVAL;

    retval = xhci_suspend(xhci);

    return retval;
}
Beispiel #8
0
static int __maybe_unused xhci_histb_suspend(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);
	int ret;

	ret = xhci_suspend(xhci, device_may_wakeup(dev));

	if (!device_may_wakeup(dev))
		xhci_histb_host_disable(histb);

	return ret;
}
static int exynos_xhci_suspend(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;

	/* Prevent any more root-hub status calls from the timer
	 * The HCD might still restart the timer (if a port status change
	 * interrupt occurs), but usb_hcd_poll_rh_status() won't invoke
	 * the hub_status_data() callback.
	 */
	hcd->rh_pollable = 0;
	hcd->shared_hcd->rh_pollable = 0;

	xhci = hcd_to_xhci(hcd);

	if (hcd->state != HC_STATE_SUSPENDED ||
			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
		dev_err(dev, "%s: HC state is not suspended!\n", __func__);
#ifdef CONFIG_USB_SUSPEND
	if (pm_runtime_suspended(dev)) {
		dev_dbg(dev, "xhci is runtime suspended\n");
		return 0;
	}
#endif
	retval = xhci_suspend(xhci, 0);
	if (retval < 0)
		dev_err(dev, "%s: cannot stop xHC\n", __func__);

	pm_runtime_put_sync(dev->parent);

	exynos_drd_put(pdev);

	return retval;
}
Beispiel #10
0
static int xhci_plat_suspend(struct device *dev)
{
	struct usb_hcd	*hcd = dev_get_drvdata(dev);
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);

	/*
	 * xhci_suspend() needs `do_wakeup` to know whether host is allowed
	 * to do wakeup during suspend. Since xhci_plat_suspend is currently
	 * only designed for system suspend, device_may_wakeup() is enough
	 * to dertermine whether host is allowed to do wakeup. Need to
	 * reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
	 * also applies to runtime suspend.
	 */
	return xhci_suspend(xhci, device_may_wakeup(dev));
}
Beispiel #11
0
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int	retval = 0;

	if (hcd->state != HC_STATE_SUSPENDED ||
			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
		return -EINVAL;

	if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
		xhci_pme_quirk(xhci);

	retval = xhci_suspend(xhci, do_wakeup);

	return retval;
}
Beispiel #12
0
static int exynos_xhci_suspend(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;

    xhci = hcd_to_xhci(hcd);

    if (hcd->state != HC_STATE_SUSPENDED ||
            xhci->shared_hcd->state != HC_STATE_SUSPENDED)
        dev_err(dev, "%s: HC state is not suspended!\n", __func__);
#ifdef CONFIG_USB_SUSPEND
    if (pm_runtime_suspended(dev)) {
        dev_dbg(dev, "xhci is runtime suspended\n");
        return 0;
    }
#endif
    retval = xhci_suspend(xhci);
    if (retval < 0)
        dev_err(dev, "%s: cannot stop xHC\n", __func__);

    pm_runtime_put_sync(dev->parent);

    exynos_drd_put(pdev);

    return retval;
}
static int exynos_xhci_runtime_suspend(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;

	xhci = hcd_to_xhci(hcd);

	if (hcd->state != HC_STATE_SUSPENDED ||
			xhci->shared_hcd->state != HC_STATE_SUSPENDED) {
		dev_dbg(dev, "%s: HC state is not suspended!\n", __func__);
		return -EAGAIN;
	}

	retval = xhci_suspend(xhci, 0);
	if (retval < 0)
		dev_err(dev, "%s: cannot stop xHC\n", __func__);

	pm_runtime_put_sync(exynos_xhci->dev->parent);

	exynos_drd_put(pdev);

	return retval;
}
/* 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;

}
static int xhci_pci_suspend(struct usb_hcd *hcd)
{
    struct xhci_hcd	*xhci = hcd_to_xhci(hcd);

    return xhci_suspend(xhci);
}