From 2b5d53c9ffec5d7478731a8b8cb22872e07070d2 Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Tue, 9 Mar 2021 23:11:48 +0530 Subject: [PATCH] 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 --- drivers/usb/dwc3/dwc3-msm.c | 88 +++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 8c41ac335265..1f98f69ef4ca 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -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",