OSDN Git Service

usb: dwc3: Determine connection speed for HS PHY
authorDevdutt Patnaik <dpatnaik@codeaurora.org>
Tue, 21 Jun 2016 00:09:37 +0000 (17:09 -0700)
committerHemant Kumar <hemantk@codeaurora.org>
Wed, 20 Jul 2016 18:34:47 +0000 (11:34 -0700)
DP/DM linestate is needed by the QUSB2 PHY driver to configure the
polarity of DP/DM transition triggers for exiting low power mode.
This was previously available via the  QUSB2PHY_PORT_UTMI_STATUS
PHY register which is now deprecated. In order to correctly determine
the interrupt polarity we need to pass the current operating speed
to the QUSB2 PHY driver. The PHY driver uses mode, speed and
cable connection status to determine the linestate and configure
interrupt polarities for wake up. Add logic to determine operating
speed for host and device mode cases.

Change-Id: Iaede1269f514a314bd9717a33100f748e7753b2a
Signed-off-by: Devdutt Patnaik <dpatnaik@codeaurora.org>
drivers/usb/dwc3/dwc3-msm.c
include/linux/usb/msm_hsusb.h

index f9c0b6a..1f59714 100644 (file)
@@ -1794,6 +1794,36 @@ static void dwc3_msm_bus_vote_w(struct work_struct *w)
                dev_err(mdwc->dev, "Failed to reset bus bw vote %d\n", ret);
 }
 
+static void dwc3_set_phy_speed_flags(struct dwc3_msm *mdwc)
+{
+       struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+       int i, num_ports;
+       u32 reg;
+
+       mdwc->hs_phy->flags &= ~(PHY_HSFS_MODE | PHY_LS_MODE);
+       if (mdwc->in_host_mode) {
+               reg = dwc3_msm_read_reg(mdwc->base, USB3_HCSPARAMS1);
+               num_ports = HCS_MAX_PORTS(reg);
+               for (i = 0; i < num_ports; i++) {
+                       reg = dwc3_msm_read_reg(mdwc->base,
+                                       USB3_PORTSC + i*0x10);
+                       if (reg & PORT_PE) {
+                               if (DEV_HIGHSPEED(reg) || DEV_FULLSPEED(reg))
+                                       mdwc->hs_phy->flags |= PHY_HSFS_MODE;
+                               else if (DEV_LOWSPEED(reg))
+                                       mdwc->hs_phy->flags |= PHY_LS_MODE;
+                       }
+               }
+       } else {
+               if (dwc->gadget.speed == USB_SPEED_HIGH ||
+                       dwc->gadget.speed == USB_SPEED_FULL)
+                       mdwc->hs_phy->flags |= PHY_HSFS_MODE;
+               else if (dwc->gadget.speed == USB_SPEED_LOW)
+                       mdwc->hs_phy->flags |= PHY_LS_MODE;
+       }
+}
+
+
 static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
 {
        int ret, i;
@@ -1867,6 +1897,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
        /* disable power event irq, hs and ss phy irq is used as wake up src */
        disable_irq(mdwc->pwr_event_irq);
 
+       dwc3_set_phy_speed_flags(mdwc);
        /* Suspend HS PHY */
        usb_phy_set_suspend(mdwc->hs_phy, 1);
 
@@ -2016,6 +2047,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
                mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND;
        }
 
+       mdwc->hs_phy->flags &= ~(PHY_HSFS_MODE | PHY_LS_MODE);
        /* Resume HS PHY */
        usb_phy_set_suspend(mdwc->hs_phy, 0);
 
index 89effb6..44b6222 100644 (file)
@@ -176,6 +176,8 @@ struct msm_usb_cable {
 #define DEVICE_IN_SS_MODE              BIT(5)
 #define PHY_LANE_A                     BIT(6)
 #define PHY_LANE_B                     BIT(7)
+#define PHY_HSFS_MODE                  BIT(8)
+#define PHY_LS_MODE                    BIT(9)
 
 #define USB_NUM_BUS_CLOCKS      3