/**
 * 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;
}