From c5bf1235d7d1c1b629fda7f321b33671d9705b1f Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Wed, 19 Jul 2023 19:29:10 +0530 Subject: [PATCH 06/11] usb: dwc3: qcom: Refactor IRQ handling in QCOM Glue driver Refactor setup_irq call to facilitate reading multiport IRQ's along with non mulitport ones. Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 196 ++++++++++++++++++++++++----------- 1 file changed, 137 insertions(+), 59 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 3de43df6bbe8..ab8664ced255 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -74,9 +74,9 @@ struct dwc3_qcom { struct reset_control *resets; int hs_phy_irq; - int dp_hs_phy_irq; - int dm_hs_phy_irq; - int ss_phy_irq; + int dp_hs_phy_irq[DWC3_MAX_PORTS]; + int dm_hs_phy_irq[DWC3_MAX_PORTS]; + int ss_phy_irq[DWC3_MAX_PORTS]; enum usb_device_speed usb2_speed; struct extcon_dev *edev; @@ -93,6 +93,42 @@ struct dwc3_qcom { struct icc_path *icc_path_apps; }; +struct dwc3_qcom_irq_info { + char *dt_name; + char *disp_name; + bool acpi_variant_present; +}; + +const struct dwc3_qcom_irq_info non_mp_irq_info[4] = { + { "hs_phy_irq", "qcom_dwc3 HS", true, }, + { "dp_hs_phy_irq", "qcom_dwc3 DP_HS", true, }, + { "dm_hs_phy_irq", "qcom_dwc3 DM_HS", true, }, + { "ss_phy_irq", "qcom_dwc3 SS", true, }, +}; + +const struct dwc3_qcom_irq_info mp_irq_info[3][DWC3_MAX_PORTS] = { + { + { "dp_hs_phy_1", "qcom_dwc3 DP_HS1", false }, + { "dp_hs_phy_2", "qcom_dwc3 DP_HS2", false }, + { "dp_hs_phy_3", "qcom_dwc3 DP_HS3", false }, + { "dp_hs_phy_4", "qcom_dwc3 DP_HS4", false }, + }, + + { + { "dm_hs_phy_1", "qcom_dwc3 DM_HS1", false }, + { "dm_hs_phy_2", "qcom_dwc3 DM_HS2", false }, + { "dm_hs_phy_3", "qcom_dwc3 DM_HS3", false }, + { "dm_hs_phy_4", "qcom_dwc3 DM_HS4", false }, + }, + + { + { "ss_phy_1", "qcom_dwc3 SS1", false }, + { "ss_phy_2", "qcom_dwc3 SS2", false }, + { "ss_phy_3", "qcom_dwc3 SS3", false }, + { "ss_phy_4", "qcom_dwc3 SS4", false }, + }, +}; + static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) { u32 reg; @@ -375,16 +411,16 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) dwc3_qcom_disable_wakeup_irq(qcom->hs_phy_irq); if (qcom->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq); + dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq[0]); } else if ((qcom->usb2_speed == USB_SPEED_HIGH) || (qcom->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq); + dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq[0]); } else { - dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq); - dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq); + dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq[0]); + dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq[0]); } - dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq); + dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq[0]); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -401,20 +437,20 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) */ if (qcom->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq[0], IRQ_TYPE_EDGE_FALLING); } else if ((qcom->usb2_speed == USB_SPEED_HIGH) || (qcom->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq[0], IRQ_TYPE_EDGE_FALLING); } else { - dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq[0], IRQ_TYPE_EDGE_RISING); - dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq[0], IRQ_TYPE_EDGE_RISING); } - dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0); + dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq[0], 0); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -535,72 +571,114 @@ static int dwc3_qcom_get_irq(struct platform_device *pdev, return ret; } +static int dwc3_qcom_prep_irq(struct dwc3_qcom *qcom, char *irq_name, + char *disp_name, int irq) +{ + int ret; + + /* Keep wakeup interrupts disabled until suspend */ + irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = devm_request_threaded_irq(qcom->dev, irq, NULL, + qcom_dwc3_resume_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + disp_name, qcom); + if (ret) + dev_err(qcom->dev, "%s failed: %d\n", irq_name, ret); + + return ret; +} + static int dwc3_qcom_setup_irq(struct platform_device *pdev) { struct dwc3_qcom *qcom = platform_get_drvdata(pdev); const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; + char *disp_name; + char *dt_name; + int index; int irq; int ret; + int i; - irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", + irq = dwc3_qcom_get_irq(pdev, non_mp_irq_info[0].dt_name, pdata ? pdata->hs_phy_irq_index : -1); if (irq > 0) { - /* Keep wakeup interrupts disabled until suspend */ - irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(qcom->dev, irq, NULL, - qcom_dwc3_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "qcom_dwc3 HS", qcom); - if (ret) { - dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); + ret = dwc3_qcom_prep_irq(qcom, non_mp_irq_info[0].dt_name, + non_mp_irq_info[0].disp_name, irq); + if (ret) return ret; - } qcom->hs_phy_irq = irq; } - irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq", - pdata ? pdata->dp_hs_phy_irq_index : -1); - if (irq > 0) { - irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(qcom->dev, irq, NULL, - qcom_dwc3_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "qcom_dwc3 DP_HS", qcom); - if (ret) { - dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); - return ret; + for (i = 0; i < DWC3_MAX_PORTS; i++) { + dt_name = mp_irq_info[0][i].dt_name; + disp_name = mp_irq_info[0][i].disp_name; + index = (mp_irq_info[0][i].acpi_variant_present && pdata) ? + pdata->dp_hs_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + if ((irq < 0) && (i == 0)) { + dt_name = non_mp_irq_info[1].dt_name; + disp_name = non_mp_irq_info[1].disp_name; + index = (non_mp_irq_info[1].acpi_variant_present && pdata) ? + pdata->dp_hs_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + } + + if (irq > 0) { + ret = dwc3_qcom_prep_irq(qcom, dt_name, disp_name, irq); + if (ret) + return ret; + qcom->dp_hs_phy_irq[i] = irq; } - qcom->dp_hs_phy_irq = irq; } - irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq", - pdata ? pdata->dm_hs_phy_irq_index : -1); - if (irq > 0) { - irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(qcom->dev, irq, NULL, - qcom_dwc3_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "qcom_dwc3 DM_HS", qcom); - if (ret) { - dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); - return ret; + for (i = 0; i < DWC3_MAX_PORTS; i++) { + dt_name = mp_irq_info[1][i].dt_name; + disp_name = mp_irq_info[1][i].disp_name; + index = (mp_irq_info[1][i].acpi_variant_present && pdata) ? + pdata->dm_hs_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + if ((irq < 0) && (i == 0)) { + dt_name = non_mp_irq_info[2].dt_name; + disp_name = non_mp_irq_info[2].disp_name; + index = (non_mp_irq_info[2].acpi_variant_present && pdata) ? + pdata->dp_hs_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + } + + if (irq > 0) { + ret = dwc3_qcom_prep_irq(qcom, dt_name, disp_name, irq); + if (ret) + return ret; + qcom->dm_hs_phy_irq[i] = irq; } - qcom->dm_hs_phy_irq = irq; } - irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq", - pdata ? pdata->ss_phy_irq_index : -1); - if (irq > 0) { - irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(qcom->dev, irq, NULL, - qcom_dwc3_resume_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "qcom_dwc3 SS", qcom); - if (ret) { - dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); - return ret; + for (i = 0; i < DWC3_MAX_PORTS; i++) { + dt_name = mp_irq_info[2][i].dt_name; + disp_name = mp_irq_info[2][i].disp_name; + index = (mp_irq_info[2][i].acpi_variant_present && pdata) ? + pdata->ss_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + if ((irq < 0) && (i == 0)) { + dt_name = non_mp_irq_info[3].dt_name; + disp_name = non_mp_irq_info[3].disp_name; + index = (non_mp_irq_info[3].acpi_variant_present && pdata) ? + pdata->dp_hs_phy_irq_index : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, index); + } + + if (irq > 0) { + ret = dwc3_qcom_prep_irq(qcom, dt_name, disp_name, irq); + if (ret) + return ret; + qcom->ss_phy_irq[i] = irq; } - qcom->ss_phy_irq = irq; } return 0; -- 2.40.0