lkml.org 
[lkml]   [2023]   [Oct]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v13 05/10] usb: dwc3: qcom: Refactor IRQ handling in QCOM Glue driver
    Date
    Refactor setup_irq call to facilitate reading multiport IRQ's along
    with non mulitport ones. Read through the interrupt-names property
    to figure out, the type of interrupt (DP/DM/HS/SS) and to which port
    it belongs. Also keep track of port index to calculate port count
    based on interrupts provided as input in DT.

    Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
    ---
    drivers/usb/dwc3/dwc3-qcom.c | 210 +++++++++++++++++++++++++----------
    1 file changed, 154 insertions(+), 56 deletions(-)

    diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
    index ef2006db7601..863892284146 100644
    --- a/drivers/usb/dwc3/dwc3-qcom.c
    +++ b/drivers/usb/dwc3/dwc3-qcom.c
    @@ -53,14 +53,25 @@
    #define APPS_USB_AVG_BW 0
    #define APPS_USB_PEAK_BW MBps_to_icc(40)

    +#define NUM_PHY_IRQ 4
    +
    +enum dwc3_qcom_ph_index {
    + DP_HS_PHY_IRQ_INDEX = 0,
    + DM_HS_PHY_IRQ_INDEX,
    + SS_PHY_IRQ_INDEX,
    + HS_PHY_IRQ_INDEX,
    +};
    +
    struct dwc3_acpi_pdata {
    u32 qscratch_base_offset;
    u32 qscratch_base_size;
    u32 dwc3_core_base_size;
    + /*
    + * The phy_irq_index corresponds to ACPI indexes of (in order) DP/DM/SS
    + * IRQ's respectively.
    + */
    + 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 +84,12 @@ struct dwc3_qcom {
    int num_clocks;
    struct reset_control *resets;

    + /*
    + * The phy_irq corresponds to IRQ's registered for (in order) DP/DM/SS
    + * respectively.
    + */
    + int phy_irq[NUM_PHY_IRQ - 1][DWC3_MAX_PORTS];
    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;
    @@ -91,6 +104,7 @@ 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 +389,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[DM_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[DP_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 +415,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[DM_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[DP_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)
    @@ -535,8 +549,8 @@ 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)
    +static int dwc3_qcom_prep_irq(struct dwc3_qcom *qcom, const char *irq_name,
    + const char *disp_name, int irq)
    {
    int ret;

    @@ -553,47 +567,135 @@ 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", strlen("dp_hs_phy")) == 0)
    + irq_index = DP_HS_PHY_IRQ_INDEX;
    + else if (strncmp(irq_name, "dm_hs_phy", strlen("dm_hs_phy")) == 0)
    + irq_index = DM_HS_PHY_IRQ_INDEX;
    + else if (strncmp(irq_name, "ss_phy", strlen("ss_phy")) == 0)
    + irq_index = SS_PHY_IRQ_INDEX;
    + else if (strncmp(irq_name, "hs_phy", strlen("hs_phy")) == 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;
    + }
    +
    + if (port_index > DWC3_MAX_PORTS)
    + port_index = -1;
    +
    + 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;
    +
    + /*
    + * Currently multiport supported targets don't have an ACPI variant.
    + * So return -1 if we are not dealing with first port of the controller.
    + */
    + if ((pdata == NULL) || (port_index != 1))
    + goto done;
    +
    + if (irq_index == HS_PHY_IRQ_INDEX)
    + acpi_index = pdata->hs_phy_irq_index;
    + else
    + 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, "Invalid 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);
    + if (port_index == -1) {
    + dev_dbg(&pdev->dev, "Port index invalid. IRQ not handled");
    + continue;
    + }

    - 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;
    + acpi_index = dwc3_qcom_get_acpi_index(qcom, irq_index, port_index);
    +
    + 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;
    @@ -1026,20 +1128,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.42.0
    \
     
     \ /
      Last update: 2023-10-07 17:49    [W:3.101 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site