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: Ajay Agarwal <ajaya@codeaurora.org>
This commit is contained in:
Ajay Agarwal 2021-03-09 23:11:48 +05:30
commit 2b5d53c9ff

View file

@ -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",