usb: dwc3: rockchip: power off usb2 phy in suspend
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc3 / dwc3-rockchip.c
index b9f4d6f532794c71c705e5a3286d4aefbfaf5d93..a7444d17c66ca96f7206ec518cc02598182313dc 100644 (file)
@@ -595,22 +595,45 @@ static int dwc3_rockchip_runtime_resume(struct device *dev)
 static int dwc3_rockchip_suspend(struct device *dev)
 {
        struct dwc3_rockchip *rockchip = dev_get_drvdata(dev);
+       struct dwc3 *dwc = rockchip->dwc;
 
        rockchip->suspended = true;
        cancel_work_sync(&rockchip->otg_work);
 
+       if (rockchip->edev && dwc->dr_mode != USB_DR_MODE_PERIPHERAL) {
+               /*
+                * If USB HOST connected, we will do phy power
+                * on in extcon evt work, so need to do phy
+                * power off in suspend. And we just power off
+                * USB2 PHY here because USB3 PHY power on operation
+                * need to be done while DWC3 controller is in P2
+                * state, but after resume DWC3 controller is in
+                * P0 state. So we put USB3 PHY in power on state.
+                */
+               if (extcon_get_cable_state_(rockchip->edev,
+                                           EXTCON_USB_HOST) > 0)
+                       phy_power_off(dwc->usb2_generic_phy);
+       }
+
        return 0;
 }
 
 static int dwc3_rockchip_resume(struct device *dev)
 {
        struct dwc3_rockchip *rockchip = dev_get_drvdata(dev);
+       struct dwc3 *dwc = rockchip->dwc;
 
        rockchip->suspended = false;
 
        if (rockchip->edev)
                schedule_work(&rockchip->otg_work);
 
+       if (rockchip->edev && dwc->dr_mode != USB_DR_MODE_PERIPHERAL) {
+               if (extcon_get_cable_state_(rockchip->edev,
+                                           EXTCON_USB_HOST) > 0)
+                       phy_power_on(dwc->usb2_generic_phy);
+       }
+
        return 0;
 }