/** * Performs QMP PHY suspend/resume functionality. * * @uphy - usb phy pointer. * @suspend - to enable suspend or not. 1 - suspend, 0 - resume * */ static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend) { struct msm_ssphy_qmp *phy = container_of(uphy, struct msm_ssphy_qmp, phy); dev_dbg(uphy->dev, "QMP PHY set_suspend for %s called with cable %s\n", (suspend ? "suspend" : "resume"), get_cable_status_str(phy)); /* * The dwc3 probe function calls set_suspend on both phys. This prevent * a situation where would try writing to registers without the phy * init function being called first. */ if (!phy->clk_enabled) { dev_dbg(uphy->dev, "clocks not enabled yet\n"); return -EAGAIN; } if (phy->cable_connected && phy->in_suspend && suspend) { dev_dbg(uphy->dev, "%s: USB PHY is already suspended\n", __func__); return 0; } if (suspend) { msm_ssusb_qmp_enable_autonomous(phy); if (!phy->cable_connected) { clk_disable_unprepare(phy->pipe_clk); writel_relaxed(0x00, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL); } clk_disable_unprepare(phy->cfg_ahb_clk); clk_disable_unprepare(phy->aux_clk); phy->in_suspend = true; msm_ssphy_power_enable(phy, 0); dev_dbg(uphy->dev, "QMP PHY is suspend\n"); } else { msm_ssphy_power_enable(phy, 1); clk_prepare_enable(phy->aux_clk); clk_prepare_enable(phy->cfg_ahb_clk); if (!phy->cable_connected) { clk_prepare_enable(phy->pipe_clk); writel_relaxed(0x01, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL); } msm_ssusb_qmp_enable_autonomous(phy); phy->in_suspend = false; dev_dbg(uphy->dev, "QMP PHY is resumed\n"); } return 0; }
static int msm_ssphy_qmp_set_suspend(struct usb_phy *uphy, int suspend) { struct msm_ssphy_qmp *phy = container_of(uphy, struct msm_ssphy_qmp, phy); dev_info(uphy->dev, "QMP PHY set_suspend for %s called with cable %s\n", (suspend ? "suspend" : "resume"), get_cable_status_str(phy)); if (!phy->clk_enabled) { dev_info(uphy->dev, "clocks not enabled yet\n"); return -EAGAIN; } if (phy->cable_connected && phy->in_suspend && suspend) { dev_info(uphy->dev, "%s: USB PHY is already suspended\n", __func__); return 0; } if (suspend) { msm_ssusb_qmp_enable_autonomous(phy); if (!phy->cable_connected) { clk_disable_unprepare(phy->pipe_clk); writel_relaxed(0x00, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL); } clk_disable_unprepare(phy->cfg_ahb_clk); clk_disable_unprepare(phy->aux_clk); phy->in_suspend = true; msm_ssphy_power_enable(phy, 0); dev_info(uphy->dev, "QMP PHY is suspend\n"); } else { msm_ssphy_power_enable(phy, 1); clk_prepare_enable(phy->aux_clk); clk_prepare_enable(phy->cfg_ahb_clk); if (!phy->cable_connected) { clk_prepare_enable(phy->pipe_clk); writel_relaxed(0x01, phy->base + PCIE_USB3_PHY_POWER_DOWN_CONTROL); } msm_ssusb_qmp_enable_autonomous(phy); phy->in_suspend = false; dev_info(uphy->dev, "QMP PHY is resumed\n"); } return 0; }
static int msm_ssphy_qmp_notify_disconnect(struct usb_phy *uphy, enum usb_device_speed speed) { struct msm_ssphy_qmp *phy = container_of(uphy, struct msm_ssphy_qmp, phy); dev_dbg(uphy->dev, "QMP phy disconnect notification\n"); dev_dbg(uphy->dev, " cable_connected=%d\n", phy->cable_connected); msm_ssusb_qmp_enable_autonomous(phy); phy->cable_connected = false; phy->in_suspend = false; return 0; }