]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
usb: dwc3: qcom: Add multiport suspend/resume support for wrapper
authorKrishna Kurapati <quic_kriskura@quicinc.com>
Sat, 20 Apr 2024 04:49:01 +0000 (10:19 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Apr 2024 02:56:09 +0000 (19:56 -0700)
Power event IRQ is used for wakeup either when the controller is
SuperSpeed capable but is missing an SuperSpeed PHY interrupt, or when
the GIC is not capable of detecting DP/DM High-Speed PHY interrupts.

The Power event IRQ stat register indicates whether the High-Speed
phy entered and exited L2 successfully during suspend and resume.
Indicate the same for all ports of a multiport controller.

Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
Tested-by: Johan Hovold <johan+linaro@kernel.org>
Link: https://lore.kernel.org/r/20240420044901.884098-10-quic_kriskura@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/dwc3-qcom.c

index b6f13bb14e2cf79d1e96ab93a4b6a3bac755281e..88fb6706a18d38dc495f089aa706124314919279 100644 (file)
@@ -36,7 +36,6 @@
 #define PIPE3_PHYSTATUS_SW                     BIT(3)
 #define PIPE_UTMI_CLK_DIS                      BIT(8)
 
-#define PWR_EVNT_IRQ_STAT_REG                  0x58
 #define PWR_EVNT_LPM_IN_L2_MASK                        BIT(4)
 #define PWR_EVNT_LPM_OUT_L2_MASK               BIT(5)
 
 /* Qualcomm SoCs with multiport support has up to 4 ports */
 #define DWC3_QCOM_MAX_PORTS    4
 
+static const u32 pwr_evnt_irq_stat_reg[DWC3_QCOM_MAX_PORTS] = {
+       0x58,
+       0x1dc,
+       0x228,
+       0x238,
+};
+
 struct dwc3_qcom_port {
        int                     qusb2_phy_irq;
        int                     dp_hs_phy_irq;
@@ -424,9 +430,11 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
        if (qcom->is_suspended)
                return 0;
 
-       val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG);
-       if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
-               dev_err(qcom->dev, "HS-PHY not in L2\n");
+       for (i = 0; i < qcom->num_ports; i++) {
+               val = readl(qcom->qscratch_base + pwr_evnt_irq_stat_reg[i]);
+               if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
+                       dev_err(qcom->dev, "port-%d HS-PHY not in L2\n", i + 1);
+       }
 
        for (i = qcom->num_clocks - 1; i >= 0; i--)
                clk_disable_unprepare(qcom->clks[i]);
@@ -475,8 +483,11 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
                dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret);
 
        /* Clear existing events from PHY related to L2 in/out */
-       dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG,
-                         PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
+       for (i = 0; i < qcom->num_ports; i++) {
+               dwc3_qcom_setbits(qcom->qscratch_base,
+                                 pwr_evnt_irq_stat_reg[i],
+                                 PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK);
+       }
 
        qcom->is_suspended = false;