From 418ac10e88c53f67e947f754aebd3bd97ea67e8a Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Tue, 22 Aug 2023 15:25:12 +0530 Subject: [PATCH 2/2] usb: dwc3: qcom: Read multiport interrupts Read multiport interrupts in qcom driver. Signed-off-by: Krishna Kurapati Change-Id: Ic2bf8cad70c1478c79eb7e9d3dc5d9082c5bb1f9 --- drivers/usb/dwc3/dwc3-qcom.c | 193 ++++++++++++++++++++++++----------- 1 file changed, 134 insertions(+), 59 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f14ddc9c541d..a0ba71ea9541 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -53,14 +53,19 @@ #define APPS_USB_AVG_BW 0 #define APPS_USB_PEAK_BW MBps_to_icc(40) +#define NUM_PHY_IRQ 4 + +#define DP_HS_PHY_IRQ_INDEX 0 +#define DM_HS_PHY_IRQ_INDEX 1 +#define SS_PHY_IRQ_INDEX 2 +#define HS_PHY_IRQ_INDEX 3 + struct dwc3_acpi_pdata { u32 qscratch_base_offset; u32 qscratch_base_size; u32 dwc3_core_base_size; + int phy_irq_index[NUM_PHY_IRQ - 1]; int hs_phy_irq_index; - int dp_hs_phy_irq_index; - int dm_hs_phy_irq_index; - int ss_phy_irq_index; bool is_urs; }; @@ -73,10 +78,8 @@ struct dwc3_qcom { 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; + int phy_irq[NUM_PHY_IRQ - 1][DWC3_MAX_PORTS]; + int hs_phy_irq; enum usb_device_speed usb2_speed; struct extcon_dev *edev; @@ -91,6 +94,8 @@ struct dwc3_qcom { bool pm_suspended; struct icc_path *icc_path_ddr; struct icc_path *icc_path_apps; + + int num_ports; }; static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) @@ -375,16 +380,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->phy_irq[DP_HS_PHY_IRQ_INDEX][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->phy_irq[DM_HS_PHY_IRQ_INDEX][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->phy_irq[DP_HS_PHY_IRQ_INDEX][0]); + dwc3_qcom_disable_wakeup_irq(qcom->phy_irq[DM_HS_PHY_IRQ_INDEX][0]); } - dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq); + dwc3_qcom_disable_wakeup_irq(qcom->phy_irq[SS_PHY_IRQ_INDEX][0]); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -401,20 +406,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->phy_irq[DP_HS_PHY_IRQ_INDEX][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->phy_irq[DM_HS_PHY_IRQ_INDEX][0], IRQ_TYPE_EDGE_FALLING); } else { - dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->phy_irq[DP_HS_PHY_IRQ_INDEX][0], IRQ_TYPE_EDGE_RISING); - dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq, + dwc3_qcom_enable_wakeup_irq(qcom->phy_irq[DM_HS_PHY_IRQ_INDEX][0], IRQ_TYPE_EDGE_RISING); } - dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0); + dwc3_qcom_enable_wakeup_irq(qcom->phy_irq[SS_PHY_IRQ_INDEX][0], 0); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -553,51 +558,125 @@ static int dwc3_qcom_prep_irq(struct dwc3_qcom *qcom, char *irq_name, return ret; } +static int dwc3_qcom_get_irq_index(const char *irq_name) +{ + /* + * If we are reading IRQ not supported by the driver + * like pwr_event_irq, then return -1 indicating the next + * helper function to skip processing IRQ name further. + */ + int irq_index = -1; + + if (strncmp(irq_name, "dp_hs_phy", 9) == 0) + irq_index = DP_HS_PHY_IRQ_INDEX; + else if(strncmp(irq_name, "dm_hs_phy", 9) == 0) + irq_index = DM_HS_PHY_IRQ_INDEX; + else if(strncmp(irq_name, "ss_phy", 6) == 0) + irq_index = SS_PHY_IRQ_INDEX; + else if(strncmp(irq_name, "hs_phy", 6) == 0) + irq_index = HS_PHY_IRQ_INDEX; + + return irq_index; +} + +static int dwc3_qcom_get_port_index(const char *irq_name, int irq_index) +{ + int port_index = -1; + + switch (irq_index) { + case DP_HS_PHY_IRQ_INDEX: + if (strcmp(irq_name, "dp_hs_phy_irq") == 0) + port_index = 1; + else + sscanf(irq_name, "dp_hs_phy_%d", &port_index); + break; + + case DM_HS_PHY_IRQ_INDEX: + if (strcmp(irq_name, "dm_hs_phy_irq") == 0) + port_index = 1; + else + sscanf(irq_name, "dm_hs_phy_%d", &port_index); + break; + + case SS_PHY_IRQ_INDEX: + if (strcmp(irq_name, "ss_phy_irq") == 0) + port_index = 1; + else + sscanf(irq_name, "ss_phy_%d", &port_index); + break; + + case HS_PHY_IRQ_INDEX: + port_index = 1; + break; + } + +done: + return port_index; +} + +static int dwc3_qcom_get_acpi_index(struct dwc3_qcom *qcom, int irq_index, + int port_index) +{ + const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; + int acpi_index = -1; + + if ((pdata == NULL) || (port_index != 1)) + goto done; + + if (irq_index == HS_PHY_IRQ_INDEX) + acpi_index = pdata->hs_phy_irq_index; + else if (port_index != -1) + acpi_index = pdata->phy_irq_index[irq_index]; + +done: + return acpi_index; +} + 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; + struct device_node *np = pdev->dev.of_node; + const char **irq_names; + int port_index; + int acpi_index; + int irq_count; + int irq_index; 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) { - ret = dwc3_qcom_prep_irq(qcom, "hs_phy_irq", - "qcom_dwc3 HS", irq); - if (ret) - return ret; - qcom->hs_phy_irq = irq; - } + irq_count = of_property_count_strings(np, "interrupt-names"); + irq_names = devm_kzalloc(&pdev->dev, sizeof(*irq_names) * irq_count, GFP_KERNEL); + if (!irq_names) + return -ENOMEM; - irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq", - pdata ? pdata->dp_hs_phy_irq_index : -1); - if (irq > 0) { - ret = dwc3_qcom_prep_irq(qcom, "dp_hs_phy_irq", - "qcom_dwc3 DP_HS", irq); - if (ret) - return ret; - qcom->dp_hs_phy_irq = irq; - } + ret = of_property_read_string_array(np, "interrupt-names", + irq_names, irq_count); + for (i = 0; i < irq_count; i++) { + irq_index = dwc3_qcom_get_irq_index(irq_names[i]); + if (irq_index == -1) { + dev_dbg(&pdev->dev, "IRQ not handled"); + continue; + } - irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq", - pdata ? pdata->dm_hs_phy_irq_index : -1); - if (irq > 0) { - ret = dwc3_qcom_prep_irq(qcom, "dm_hs_phy_irq", - "qcom_dwc3 DM_HS", irq); - if (ret) - return ret; - qcom->dm_hs_phy_irq = irq; - } + port_index = dwc3_qcom_get_port_index(irq_names[i], irq_index); + acpi_index = dwc3_qcom_get_acpi_index(qcom, irq_index, port_index); - irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq", - pdata ? pdata->ss_phy_irq_index : -1); - if (irq > 0) { - ret = dwc3_qcom_prep_irq(qcom, "ss_phy_irq", - "qcom_dwc3 SS", irq); - if (ret) - return ret; - qcom->ss_phy_irq = irq; + irq = dwc3_qcom_get_irq(pdev, irq_names[i], acpi_index); + if (irq > 0) { + ret = dwc3_qcom_prep_irq(qcom, irq_names[i], + irq_names[i], irq); + if (ret) + return ret; + + if (irq_index == HS_PHY_IRQ_INDEX) + qcom->hs_phy_irq = irq; + else + qcom->phy_irq[irq_index][port_index-1] = irq; + + if (qcom->num_ports < port_index) + qcom->num_ports = port_index; + } } return 0; @@ -1030,20 +1109,16 @@ static const struct dwc3_acpi_pdata sdm845_acpi_pdata = { .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET, .qscratch_base_size = SDM845_QSCRATCH_SIZE, .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE, + .phy_irq_index = {4, 3, 2}, .hs_phy_irq_index = 1, - .dp_hs_phy_irq_index = 4, - .dm_hs_phy_irq_index = 3, - .ss_phy_irq_index = 2 }; static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = { .qscratch_base_offset = SDM845_QSCRATCH_BASE_OFFSET, .qscratch_base_size = SDM845_QSCRATCH_SIZE, .dwc3_core_base_size = SDM845_DWC3_CORE_SIZE, + .phy_irq_index = {4, 3, 2}, .hs_phy_irq_index = 1, - .dp_hs_phy_irq_index = 4, - .dm_hs_phy_irq_index = 3, - .ss_phy_irq_index = 2, .is_urs = true, }; -- 2.40.0