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

Commit 2b5d53c9 authored by Ajay Agarwal's avatar Ajay Agarwal
Browse files

usb: dwc3-msm: Mandate pwr_evt_irq only for cores allowing SSPHY suspend



Currently the driver requires pwr_evt_irq to be compulsorily
passed from DT unless the core is dual port. Now consider a core
that does not allow SSPHY autosuspend during operational mode,
instead allowing it only as a part of dwc3_msm_ssphy_autosuspend.
As soon as autosuspend is enabled, there is a chance that
pwr_evt_irq is fired with IN_P3 bit set. Although the driver will
be marking mdwc->in_p3 in the pwr_evt_handler, it will fail to
see IN_P3 bit to be set(because it has been cleared in handler)
during the 5ms wait time in the ssphy_autosuspend function and
prepare_suspend will again set mdwc->in_p3 to 0. This leads to
failure of runtime/system suspend.
Fix this by not passing pwr_evt_irq from DT for the cores which
disable SSPHY autosuspend.

Change-Id: I85ca7e45337fe35c570d163766e7638e11537201
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent bb168a0f
Loading
Loading
Loading
Loading
+45 −43
Original line number Diff line number Diff line
@@ -4530,36 +4530,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		mdwc->lpm_to_suspend_delay = 0;
	}

	for (i = 0; i < USB_MAX_IRQ; i++) {
		mdwc->wakeup_irq[i].irq = platform_get_irq_byname(pdev,
					usb_irq_info[i].name);
		/* pwr_evnt_irq is only mandatory irq for single port core */
		if (mdwc->wakeup_irq[i].irq < 0) {
			if (!mdwc->dual_port && usb_irq_info[i].required) {
				dev_err(&pdev->dev, "get_irq for %s failed\n\n",
						usb_irq_info[i].name);
				ret = -EINVAL;
				goto err;
			}
			mdwc->wakeup_irq[i].irq = 0;
		} else {
			irq_set_status_flags(mdwc->wakeup_irq[i].irq,
						IRQ_NOAUTOEN);

			ret = devm_request_threaded_irq(&pdev->dev,
					mdwc->wakeup_irq[i].irq,
					msm_dwc3_pwr_irq,
					msm_dwc3_pwr_irq_thread,
					usb_irq_info[i].irq_type,
					usb_irq_info[i].name, mdwc);
			if (ret) {
				dev_err(&pdev->dev, "irq req %s failed: %d\n\n",
						usb_irq_info[i].name, ret);
				goto err;
			}
		}
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core_base");
	if (!res) {
		dev_err(&pdev->dev, "missing memory base resource\n");
@@ -4606,19 +4576,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		}
	}

	dwc3_init_dbm(mdwc);

	/* Add power event if the dbm indicates coming out of L1 by interrupt */
	if (!mdwc->dbm_is_1p4) {
		/* Dual port core does not need pwr_evnt_irq */
		if (!mdwc->dual_port && !mdwc->wakeup_irq[PWR_EVNT_IRQ].irq) {
			dev_err(&pdev->dev,
				"need pwr_event_irq exiting L1\n");
			ret = -EINVAL;
			goto err;
		}
	}

	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
				 &mdwc->tx_fifo_size))
		dev_err(&pdev->dev,
@@ -4745,6 +4702,51 @@ static int dwc3_msm_probe(struct platform_device *pdev)
		goto put_dwc3;
	}

	for (i = 0; i < USB_MAX_IRQ; i++) {
		mdwc->wakeup_irq[i].irq = platform_get_irq_byname(pdev,
					usb_irq_info[i].name);
		/* pwr_evnt_irq is mandatory for cores allowing SSPHY suspend */
		if (mdwc->wakeup_irq[i].irq < 0) {
			if (!dwc->dis_u3_susphy_quirk &&
					usb_irq_info[i].required) {
				dev_err(&pdev->dev, "get_irq for %s failed\n\n",
						usb_irq_info[i].name);
				ret = -EINVAL;
				goto put_dwc3;
			}
			mdwc->wakeup_irq[i].irq = 0;
		} else {
			irq_set_status_flags(mdwc->wakeup_irq[i].irq,
						IRQ_NOAUTOEN);

			ret = devm_request_threaded_irq(&pdev->dev,
					mdwc->wakeup_irq[i].irq,
					msm_dwc3_pwr_irq,
					msm_dwc3_pwr_irq_thread,
					usb_irq_info[i].irq_type,
					usb_irq_info[i].name, mdwc);
			if (ret) {
				dev_err(&pdev->dev, "irq req %s failed: %d\n\n",
						usb_irq_info[i].name, ret);
				goto put_dwc3;
			}
		}
	}

	dwc3_init_dbm(mdwc);

	/* Add power event if the dbm indicates coming out of L1 by interrupt */
	if (!mdwc->dbm_is_1p4) {
		/* pwr_evnt_irq is mandatory for cores allowing SSPHY suspend */
		if (!dwc->dis_u3_susphy_quirk &&
				!mdwc->wakeup_irq[PWR_EVNT_IRQ].irq) {
			dev_err(&pdev->dev,
				"need pwr_event_irq exiting L1\n");
			ret = -EINVAL;
			goto put_dwc3;
		}
	}

	if (of_property_read_bool(node, "qcom,ignore-wakeup-src-in-hostmode")) {
		dwc->ignore_wakeup_src_in_hostmode = true;
		dev_dbg(mdwc->dev, "%s: Allow system suspend irrespective of runtime suspend\n",