From patchwork Thu Jul 27 22:33:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krishna Kurapati PSSNV X-Patchwork-Id: 707058 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F19BBC41513 for ; Thu, 27 Jul 2023 22:34:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233194AbjG0Wew (ORCPT ); Thu, 27 Jul 2023 18:34:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49350 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233128AbjG0Wer (ORCPT ); Thu, 27 Jul 2023 18:34:47 -0400 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3560358B; Thu, 27 Jul 2023 15:34:12 -0700 (PDT) Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 36RJF92G018598; Thu, 27 Jul 2023 22:34:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=jsWb+qEQKFTty1cr8bPdRK+e2mc6+ibu0kXw6ysDFzM=; b=Kn9/XbXOftZlC3PbQB/dKZsRg4Avk5bwdtzY51/huo+Bs21ovcJov7d5XHwS8tyKgp+L erxfaSVGLNU+a4FwB+td7NZnycynNCv1LgizRX+pooDnE0n4r4DJdrc5MXgoFsiwah4Q pkzFbDhjLcLVeazZAoC+MCZwA63XvyxyIjfoWoNjYcJHZftn3D2JVfo5z7KqZxzCWJtH gFVCipHNTUrGhXDZQzWaTmpWmYSVNopX7f53er8gziKTmHwy8ezxGyKUbTCMqPLG88Ob ulhAf3IGTDIdcQ0dFxJDqCDB/UbxlQsuDgQXUK/YOMf19A+IYbXwkARzvFLu2BuxQu/F ug== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3s3k7u2594-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 27 Jul 2023 22:34:01 +0000 Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 36RMY0Cg007132 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 27 Jul 2023 22:34:00 GMT Received: from hu-kriskura-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.30; Thu, 27 Jul 2023 15:33:54 -0700 From: Krishna Kurapati To: Thinh Nguyen , Greg Kroah-Hartman , Philipp Zabel , "Andy Gross" , Bjorn Andersson , "Konrad Dybcio" , Rob Herring , Krzysztof Kozlowski , Felipe Balbi , Wesley Cheng , Johan Hovold , Mathias Nyman CC: , , , , , , , , , Krishna Kurapati Subject: [PATCH v10 06/11] usb: dwc3: qcom: Refactor IRQ handling in QCOM Glue driver Date: Fri, 28 Jul 2023 04:03:02 +0530 Message-ID: <20230727223307.8096-7-quic_kriskura@quicinc.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230727223307.8096-1-quic_kriskura@quicinc.com> References: <20230727223307.8096-1-quic_kriskura@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: uHA3XX-zuE3HNkMicqNVb6nxyEz1rRoS X-Proofpoint-ORIG-GUID: uHA3XX-zuE3HNkMicqNVb6nxyEz1rRoS X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-07-27_10,2023-07-26_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 bulkscore=0 mlxlogscore=999 suspectscore=0 priorityscore=1501 clxscore=1015 phishscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2306200000 definitions=main-2307270205 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Refactor setup_irq call to facilitate reading multiport IRQ's along with non mulitport ones. For SA8295, there are 4-DP/4-DM and 2-SS IRQ's. Check whether device is multiport capable or not and read all interrupts for DP/DM/SS on each port accordingly. Signed-off-by: Krishna Kurapati Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 277 ++++++++++++++++++++++++----------- 1 file changed, 190 insertions(+), 87 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 3de43df6bbe8..ad89ded116d3 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -64,33 +64,61 @@ struct dwc3_acpi_pdata { bool is_urs; }; +struct dwc3_qcom_of_match_data { + u8 num_ports; +}; + struct dwc3_qcom { - struct device *dev; - void __iomem *qscratch_base; - struct platform_device *dwc3; - struct platform_device *urs_usb; - struct clk **clks; - int num_clocks; - struct reset_control *resets; - - int hs_phy_irq; - int dp_hs_phy_irq; - int dm_hs_phy_irq; - int ss_phy_irq; - enum usb_device_speed usb2_speed; - - struct extcon_dev *edev; - struct extcon_dev *host_edev; - struct notifier_block vbus_nb; - struct notifier_block host_nb; + struct device *dev; + void __iomem *qscratch_base; + struct platform_device *dwc3; + struct platform_device *urs_usb; + struct clk **clks; + int num_clocks; + struct reset_control *resets; + + int hs_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; + struct extcon_dev *host_edev; + struct notifier_block vbus_nb; + struct notifier_block host_nb; + + const struct dwc3_acpi_pdata *acpi_pdata; + + enum usb_dr_mode mode; + bool is_suspended; + bool pm_suspended; + struct icc_path *icc_path_ddr; + struct icc_path *icc_path_apps; + const struct dwc3_qcom_of_match_data *data; +}; + +static const struct dwc3_qcom_of_match_data qcom_dwc3 = { + .num_ports = 1, +}; - const struct dwc3_acpi_pdata *acpi_pdata; +static const struct dwc3_qcom_of_match_data sx8280xp_qcom_dwc3 = { + .num_ports = 4, +}; - enum usb_dr_mode mode; - bool is_suspended; - bool pm_suspended; - struct icc_path *icc_path_ddr; - struct icc_path *icc_path_apps; +/* + * Driver needs to read HS/DP_HS/DM_HS/SS IRQ's. Currently, for + * SA8295 which supports mutliport, thre are 4 DP/ 4 DM/ 2 SS IRQ's + * and 1 HS IRQ present. So avoid trying to read HS_PHY_IRQ for 4 + * ports of SA8295. + */ +#define MAX_PHY_IRQ 4 + +enum dwc3_qcom_phy_irq_identifier { + HS_PHY_IRQ = 0, + DP_HS_PHY_IRQ, + DM_HS_PHY_IRQ, + SS_PHY_IRQ, }; static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) @@ -375,16 +403,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 +429,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 +563,138 @@ static int dwc3_qcom_get_irq(struct platform_device *pdev, return ret; } -static int dwc3_qcom_setup_irq(struct platform_device *pdev) +static int dwc3_qcom_prep_irq(struct dwc3_qcom *qcom, char *irq_name, + char *disp_name, int irq) { - struct dwc3_qcom *qcom = platform_get_drvdata(pdev); - const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; - int irq; int ret; - irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", - 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, + /* 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); - return ret; + disp_name, qcom); + if (ret) + dev_err(qcom->dev, "%s failed: %d\n", irq_name, ret); + + return ret; +} + +static int dwc3_get_acpi_index(const struct dwc3_acpi_pdata *pdata, int irq_index) +{ + int acpi_index = -1; + + if (!pdata) + return -1; + + if (irq_index == DP_HS_PHY_IRQ) + acpi_index = pdata->dp_hs_phy_irq_index; + else if (irq_index == DM_HS_PHY_IRQ) + acpi_index = pdata->dm_hs_phy_irq_index; + else if (irq_index == SS_PHY_IRQ) + acpi_index = pdata->ss_phy_irq_index; + + return acpi_index; +} + +static int dwc3_get_port_irq(struct platform_device *pdev, u8 port_index) +{ + struct dwc3_qcom *qcom = platform_get_drvdata(pdev); + bool is_mp_supported = (qcom->data->num_ports > 1) ? true : false; + const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; + char *disp_name; + int acpi_index; + char *dt_name; + int ret; + int irq; + int i; + + /* + * We need to read only DP/DM/SS IRQ's here. + * So loop over from 1->3 and accordingly modify respective phy_irq[]. + */ + for (i = 1; i < MAX_PHY_IRQ; i++) { + + if (!is_mp_supported && (port_index == 0)) { + if (i == DP_HS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "dp_hs_phy_irq"); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 DP_HS"); + } else if (i == DM_HS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "dm_hs_phy_irq"); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 DM_HS"); + } else if (i == SS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "ss_phy_irq"); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 SS"); + } + } else { + if (i == DP_HS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "dp_hs_phy_%d", port_index + 1); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 DP_HS%d", port_index + 1); + } else if (i == DM_HS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "dm_hs_phy_%d", port_index + 1); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 DM_HS%d", port_index + 1); + } else if (i == SS_PHY_IRQ) { + dt_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "ss_phy_%d", port_index + 1); + disp_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "qcom_dwc3 SS%d", port_index + 1); + } } - 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; + if (!dt_name || !disp_name) + return -ENOMEM; + + acpi_index = !is_mp_supported ? dwc3_get_acpi_index(pdata, i) : -1; + + irq = dwc3_qcom_get_irq(pdev, dt_name, acpi_index); + if (irq > 0) { + ret = dwc3_qcom_prep_irq(qcom, dt_name, disp_name, irq); + if (ret) + return ret; + + if (i == DP_HS_PHY_IRQ) + qcom->dp_hs_phy_irq[port_index] = irq; + else if (i == DM_HS_PHY_IRQ) + qcom->dm_hs_phy_irq[port_index] = irq; + else if (i == SS_PHY_IRQ) + qcom->ss_phy_irq[port_index] = 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); + return 0; +} + +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; + int irq; + int ret; + int i; + + irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", + pdata ? pdata->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); + ret = dwc3_qcom_prep_irq(qcom, "hs_phy_irq", "qcom_dwc3 HS",irq); + if (ret) return ret; - } - qcom->dm_hs_phy_irq = irq; + qcom->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); + for (i = 0; i < qcom->data->num_ports; i++) { + ret = dwc3_get_port_irq(pdev, i); + if (ret) return ret; - } - qcom->ss_phy_irq = irq; } return 0; @@ -811,6 +905,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev) platform_set_drvdata(pdev, qcom); qcom->dev = &pdev->dev; + qcom->data = of_device_get_match_data(qcom->dev); + if (has_acpi_companion(dev)) { qcom->acpi_pdata = acpi_device_get_match_data(dev); if (!qcom->acpi_pdata) { @@ -1023,8 +1119,15 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { }; static const struct of_device_id dwc3_qcom_of_match[] = { - { .compatible = "qcom,dwc3" }, - { } + { + .compatible = "qcom,dwc3", + .data = &qcom_dwc3, + }, + { + .compatible = "qcom,sc8280xp-dwc3-mp", + .data = &sx8280xp_qcom_dwc3, + }, + { }, }; MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);