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

Commit b720b5a0 authored by Ajay Agarwal's avatar Ajay Agarwal
Browse files

usb: host: Modify PM handling for USB interconnect platforms



Currently the PM handling power collapses the core and issues
reset-resume for all the connected devices, both during system
suspend-resume and hibernation-restore scenarios. But certain USB
interconnect platforms want the connected NAD to not undergo
reset-resume on system resume.
Modify the operations to keep the core powered up, PHY resources
ON and xhci_resume with hibernated flag as 'false' so that
suspend-resume of the connected device is done on resume from
system suspend. Keep the hibernation operation as is.
Also change the DT flag to 'qcom,ignore-wakeup-src-in-hostmode'.

Change-Id: I661494595a3e270890174e0952a67985db58706d
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 5ecd48ae
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -84,9 +84,11 @@ Optional properties :
	are supported. If omitted, assume HW supports "1.5".
- qcom,reset-ep-after-lpm-resume: If present, dbm requires ep reset after
	going to lpm
- qcom,host-poweroff-in-pm-suspend: If present, allow PM suspend to happen
	irrespective of runtimePM state of host and power collapse the core.
	This also leads to reset-resume of connected devices on PM resume.
- qcom,ignore-wakeup-src-in-hostmode: If present, PM suspend/freeze allowed
	irrespective of host runtimePM state. In PM suspend/resume case, core
	will stay powered and connected devices will just be suspended/resumed.
	In hibernation, core will power collapse and connected devices will
	reset-resume on PM restore.
- qcom,default-mode-none: If present, do not start any mode on probe for an OTG
	capable DWC3 which does not have extcon handle.
- qcom,default-mode-host: If present, start host mode on probe for an OTG
+5 −3
Original line number Diff line number Diff line
@@ -29,9 +29,11 @@ Optional properties:
  - clocks: reference to a clock
  - usb3-lpm-capable: determines if platform is USB3 LPM capable
  - quirk-broken-port-ped: set if the controller has broken port disable mechanism
  - host-poweroff-in-pm-suspend: If set, allow PM suspend to happen irrespective
    of runtimePM state of host and power collapse the core. This also leads to
    reset-resume of connected devices on PM resume.
  - ignore-wakeup-src-in-hostmode: If set, PM suspend/freeze allowed
    irrespective of host runtimePM state. In PM suspend/resume case, core will
    stay powered and connected devices will just be suspended/resumed. In
    hibernation, core will power collapse and connected devices will
    reset-resume on PM restore.

Example:
	usb@f0931000 {
+1 −1
Original line number Diff line number Diff line
@@ -1589,7 +1589,7 @@ static int dwc3_resume(struct device *dev)
		 * which is now out of LPM. This allows runtime_suspend later.
		 */
		if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
		    dwc->host_poweroff_in_pm_suspend)
		    dwc->ignore_wakeup_src_in_hostmode)
			goto runtime_set_active;

		return 0;
+6 −4
Original line number Diff line number Diff line
@@ -1205,11 +1205,13 @@ struct dwc3 {
	/* Indicate if software connect was issued by the usb_gadget_driver */
	unsigned int		softconnect:1;
	/*
	 * If true, PM suspend allowed irrespective of host runtimePM state
	 * and core will power collapse. This also leads to reset-resume of
	 * connected devices on PM resume.
	 * If true, PM suspend/freeze allowed irrespective of host runtimePM
	 * state. In PM suspend/resume case, core will stay powered and
	 * connected devices will just be suspended/resumed.
	 * In hibernation, core will power collapse and connected devices will
	 * reset-resume on PM restore.
	 */
	bool			host_poweroff_in_pm_suspend;
	bool			ignore_wakeup_src_in_hostmode;
	int			retries_on_error;
	ktime_t			last_run_stop;
};
+77 −8
Original line number Diff line number Diff line
@@ -3908,8 +3908,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		mdwc->pm_qos_latency = 0;
	}

	if (of_property_read_bool(node, "qcom,host-poweroff-in-pm-suspend")) {
		dwc->host_poweroff_in_pm_suspend = true;
	if (of_property_read_bool(node, "qcom,ignore-wakeup-src-in-hostmode")) {
		dwc->ignore_wakeup_src_in_hostmode = true;
		dev_dbg(mdwc->dev, "%s: Core power collapse on host PM suspend\n",
								__func__);
	}
@@ -4775,7 +4775,71 @@ static int dwc3_msm_pm_suspend(struct device *dev)
	 * Check if pm_suspend can proceed irrespective of runtimePM state of
	 * host.
	 */
	if (!dwc->host_poweroff_in_pm_suspend || !mdwc->in_host_mode) {
	if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) {
		if (!atomic_read(&dwc->in_lpm)) {
			dev_err(mdwc->dev, "Abort PM suspend!! (USB is outside LPM)\n");
			return -EBUSY;
		}

		atomic_set(&mdwc->pm_suspended, 1);

		return 0;
	}

	ret = dwc3_msm_suspend(mdwc, false);
	if (!ret)
		atomic_set(&mdwc->pm_suspended, 1);

	return ret;
}

static int dwc3_msm_pm_resume(struct device *dev)
{
	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);

	dev_dbg(dev, "dwc3-msm PM resume\n");
	dbg_event(0xFF, "PM Res", 0);

	/* flush to avoid race in read/write of pm_suspended */
	flush_workqueue(mdwc->dwc3_wq);
	atomic_set(&mdwc->pm_suspended, 0);

	if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) {
		/* kick in otg state machine */
		queue_work(mdwc->dwc3_wq, &mdwc->resume_work);

		return 0;
	}

	/* Resume dwc to avoid unclocked access by xhci_plat_resume */
	dwc3_msm_resume(mdwc);
	pm_runtime_disable(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);

	/* kick in otg state machine */
	queue_work(mdwc->dwc3_wq, &mdwc->resume_work);

	return 0;
}

static int dwc3_msm_pm_freeze(struct device *dev)
{
	int ret = 0;
	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);

	dev_dbg(dev, "dwc3-msm PM freeze\n");
	dbg_event(0xFF, "PM Freeze", 0);

	flush_workqueue(mdwc->dwc3_wq);

	/*
	 * Check if pm_freeze can proceed irrespective of runtimePM state of
	 * host.
	 */
	if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) {
		if (!atomic_read(&dwc->in_lpm)) {
			dev_err(mdwc->dev, "Abort PM suspend!! (USB is outside LPM)\n");
			return -EBUSY;
@@ -4806,19 +4870,19 @@ static int dwc3_msm_pm_suspend(struct device *dev)
	return ret;
}

static int dwc3_msm_pm_resume(struct device *dev)
static int dwc3_msm_pm_restore(struct device *dev)
{
	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);

	dev_dbg(dev, "dwc3-msm PM resume\n");
	dbg_event(0xFF, "PM Res", 0);
	dev_dbg(dev, "dwc3-msm PM restore\n");
	dbg_event(0xFF, "PM Restore", 0);

	/* flush to avoid race in read/write of pm_suspended */
	flush_workqueue(mdwc->dwc3_wq);
	atomic_set(&mdwc->pm_suspended, 0);

	if (!dwc->host_poweroff_in_pm_suspend || !mdwc->in_host_mode) {
	if (!dwc->ignore_wakeup_src_in_hostmode || !mdwc->in_host_mode) {
		/* kick in otg state machine */
		queue_work(mdwc->dwc3_wq, &mdwc->resume_work);

@@ -4883,7 +4947,12 @@ static int dwc3_msm_runtime_resume(struct device *dev)
#endif

static const struct dev_pm_ops dwc3_msm_dev_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(dwc3_msm_pm_suspend, dwc3_msm_pm_resume)
	.suspend	= dwc3_msm_pm_suspend,
	.resume		= dwc3_msm_pm_resume,
	.freeze		= dwc3_msm_pm_freeze,
	.thaw		= dwc3_msm_pm_restore,
	.poweroff	= dwc3_msm_pm_suspend,
	.restore	= dwc3_msm_pm_restore,
	SET_RUNTIME_PM_OPS(dwc3_msm_runtime_suspend, dwc3_msm_runtime_resume,
				dwc3_msm_runtime_idle)
};
Loading