Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d633482 authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3 / xhci_plat: Call xhci_suspend/resume when entering/exiting LPM



Before placing the controller in low power mode using runtime
suspend, if host mode is active, xhci_suspend() should be
called to properly save state, stop root hub timers and clear
the Run/Stop bit. Likewise, if the controller receives an event
not handled by the HCD IRQ while in host suspend, it should resume
the host driver accordingly.

Add calls to xhci_suspend/resume by introducing runtime PM callbacks
to the xhci_plat driver (which were previously removed in commit
9db42d39 "usb: dwc3_otg: Remove phy dependency from xhci-plat").

CRs-Fixed: 590596
Change-Id: Ifc8016d22d2ad3f5dcd51881d22846952d37667e
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent c51c319b
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -1518,9 +1518,14 @@ static void dwc3_resume_work(struct work_struct *w)
		mdwc->resume_pending = true;
	} else {
		pm_runtime_get_sync(mdwc->dev);
		if (mdwc->otg_xceiv)
		if (mdwc->otg_xceiv) {
			mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg,
							DWC3_EVENT_PHY_RESUME);
		} else if (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM) {
			struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
			pm_runtime_resume(&dwc->xhci->dev);
		}

		pm_runtime_put_noidle(mdwc->dev);
		if (mdwc->otg_xceiv && (mdwc->ext_xceiv.otg_capability)) {
			dwc3_wait_for_ext_chg_done(mdwc);
+6 −3
Original line number Diff line number Diff line
/**
 * dwc3_otg.c - DesignWare USB3 DRD Controller OTG
 *
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -231,6 +231,7 @@ static int dwc3_otg_start_host(struct usb_otg *otg, int on)
			return ret;
		}

		pm_runtime_get(dwc->dev);
		dwc3_otg_notify_host_mode(otg, on);
		dwc3_otg_set_host(otg, NULL);
		platform_device_del(dwc->xhci);
@@ -251,6 +252,7 @@ static int dwc3_otg_start_host(struct usb_otg *otg, int on)
		dwc3_post_host_reset_core_init(dwc);
		if (ext_xceiv && !ext_xceiv->otg_capability)
			dwc3_otg_reset(dotg);
		pm_runtime_put(dwc->dev);
	}

	return 0;
@@ -870,8 +872,9 @@ static void dwc3_otg_sm_work(struct work_struct *w)
			dotg->vbus_retry_count = 0;
			work = 1;
		} else {
			dev_dbg(phy->dev, "a_host state entered. Allow runtime suspend.\n");
			pm_runtime_put_sync(phy->dev);
			dev_dbg(phy->dev, "still in a_host state. Resuming root hub.\n");
			pm_runtime_resume(&dotg->dwc->xhci->dev);
			pm_runtime_put(phy->dev);
		}
		break;

+31 −1
Original line number Diff line number Diff line
@@ -146,7 +146,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
		goto release_mem_region;
	}

	pm_runtime_no_callbacks(&pdev->dev);
	if (pdev->dev.parent)
		pm_runtime_resume(pdev->dev.parent);

	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);
@@ -216,11 +218,39 @@ static int xhci_plat_remove(struct platform_device *dev)
	return 0;
}

#ifdef CONFIG_PM_RUNTIME
static int xhci_plat_runtime_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	dev_dbg(dev, "xhci-plat runtime suspend\n");

	return xhci_suspend(xhci);
}

static int xhci_plat_runtime_resume(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	dev_dbg(dev, "xhci-plat runtime resume\n");

	return xhci_resume(xhci, false);
}
#endif

static const struct dev_pm_ops xhci_plat_pm_ops = {
	SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume,
			   NULL)
};

static struct platform_driver usb_xhci_driver = {
	.probe	= xhci_plat_probe,
	.remove	= xhci_plat_remove,
	.driver	= {
		.name = "xhci-hcd",
		.pm = &xhci_plat_pm_ops,
	},
};
MODULE_ALIAS("platform:xhci-hcd");