static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy)
{
	u8 val;

	dev_info(phy->phy.dev, "enabling QMP autonomous mode with cable %s\n",
			get_cable_status_str(phy));

	
	writeb_relaxed(1, phy->base + PCIE_USB3_PHY_LFPS_RXTERM_IRQ_CLEAR);
	
	wmb();
	writeb_relaxed(0, phy->base + PCIE_USB3_PHY_LFPS_RXTERM_IRQ_CLEAR);

	val = readb_relaxed(phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);

	val |= ARCVR_DTCT_EN;
	if (phy->cable_connected) {
		val |= ALFPS_DTCT_EN;
		
		val &= ~ARCVR_DTCT_EVENT_SEL;
	} else {
		val &= ~ALFPS_DTCT_EN;
		
		val |= ARCVR_DTCT_EVENT_SEL;
	}

	writeb_relaxed(val, phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);
}
static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy)
{
	u8 val;

	dev_dbg(phy->phy.dev, "enabling QMP autonomous mode with cable %s\n",
			get_cable_status_str(phy));

	/* clear LFPS RXTERM interrupt */
	writeb_relaxed(1, phy->base + PCIE_USB3_PHY_LFPS_RXTERM_IRQ_CLEAR);
	/* flush the previous write before next write */
	wmb();
	writeb_relaxed(0, phy->base + PCIE_USB3_PHY_LFPS_RXTERM_IRQ_CLEAR);

	val = readb_relaxed(phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);

	val |= ARCVR_DTCT_EN;
	if (phy->cable_connected) {
		val |= ALFPS_DTCT_EN;
		/* Detect detach */
		val &= ~ARCVR_DTCT_EVENT_SEL;
	} else {
		val &= ~ALFPS_DTCT_EN;
		/* Detect attach */
		val |= ARCVR_DTCT_EVENT_SEL;
	}

	writeb_relaxed(val, phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);
}
Пример #3
0
/**
 * 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;
}
Пример #5
0
static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy)
{
	u8 val;

	dev_dbg(phy->phy.dev, "enabling QMP autonomous mode with cable %s\n",
			get_cable_status_str(phy));
	val = readb_relaxed(phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);

	val |= ARCVR_DTCT_EN;
	if (phy->cable_connected) {
		val |= ALFPS_DTCT_EN;
		/* Detect detach */
		val &= ~ARCVR_DTCT_EVENT_SEL;
	} else {
		val &= ~ALFPS_DTCT_EN;
		/* Detect attach */
		val |= ARCVR_DTCT_EVENT_SEL;
	}

	writeb_relaxed(val, phy->base + PCIE_USB3_PHY_AUTONOMOUS_MODE_CTRL);
}