示例#1
0
static int msm_hsphy_set_params(struct usb_phy *uphy)
{
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);
	bool host = uphy->flags & PHY_HOST_MODE;
	int hsphy_init_seq;

	/*
	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
	 * preempasis and rise/fall time.
	 */
	if (host) {
		if (override_phy_init_host)
			phy->hsphy_init_seq_host = override_phy_init_host;
		hsphy_init_seq = phy->hsphy_init_seq_host;
	} else {
		if (override_phy_init)
			phy->hsphy_init_seq = override_phy_init;
		hsphy_init_seq = phy->hsphy_init_seq;
	}

	if (!hsphy_init_seq)
		return 0;

	dev_info(uphy->dev, "set phy param for %s value=0x%08x\n",
						host ? "host" : "peripheral",
						hsphy_init_seq & 0x03FFFFFF);
	msm_usb_write_readback(phy->base,
					PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF,
					hsphy_init_seq & 0x03FFFFFF);
	msm_hsphy_param_output(uphy);

	return 0;
}
static int msm_hsphy_init(struct usb_phy *uphy)
{
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);
	u32 val;

	msm_hsphy_reset(uphy);

	/* different sequences based on core version */
	phy->core_ver = readl_relaxed(phy->base);

	/*
	 * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
	 * and disable RETENTION (power-on default is ENABLED)
	 */
	val = readl_relaxed(phy->base + HS_PHY_CTRL_REG(0));
	val |= (USB2_UTMI_CLK_EN | CLAMP_MPM_DPSE_DMSE_EN_N | RETENABLEN);

	if (uphy->flags & ENABLE_SECONDARY_PHY) {
		val &= ~(USB2_UTMI_CLK_EN | FREECLOCK_SEL);
		val |= FREECLK_DIS_WHEN_SUSP;
	}

	writel_relaxed(val, phy->base + HS_PHY_CTRL_REG(0));
	usleep_range(2000, 2200);

	if (uphy->flags & ENABLE_SECONDARY_PHY)
		msm_usb_write_readback(phy->base, GENERAL_CFG_REG,
					SEC_UTMI_FREE_CLK_GFM_SEL1,
					SEC_UTMI_FREE_CLK_GFM_SEL1);

	if (phy->core_ver >= MSM_CORE_VER_120) {
		val = readl_relaxed(phy->base + HS_PHY_CTRL_COMMON_REG);
		val |= COMMON_OTGDISABLE0 | COMMON_OTGTUNE0_DEFAULT |
			COMMON_COMMONONN | FSEL_DEFAULT | COMMON_RETENABLEN;

		if (phy->set_pllbtune) {
			val |= COMMON_PLLBTUNE | COMMON_CLKCORE;
			val &= ~COMMON_FSEL;
		}

		writel_relaxed(val, phy->base + HS_PHY_CTRL_COMMON_REG);
	}

	/*
	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
	 * preempasis and rise/fall time.
	 */
	if (override_phy_init)
		phy->hsphy_init_seq = override_phy_init;
	if (phy->hsphy_init_seq)
		msm_usb_write_readback(phy->base,
					PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF,
					phy->hsphy_init_seq & 0x03FFFFFF);

	return 0;
}
示例#3
0
/*
* write HSPHY init value to QSCRATCH reg to set HSPHY
* parameters like VBUS valid threshold, disconnect valid
* threshold, DC voltage level,preempasis and rise/fall time
*/
static int msm_hsphy_set_params(struct usb_phy *uphy)
{
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);
	bool host = uphy->flags & PHY_HOST_MODE;
	int seq = 0;

	if (override_phy_init) {
		seq = override_phy_init;
	} else if (host && phy->hsphy_host_init_seq) {
		seq = phy->hsphy_host_init_seq;
	} else {
		seq = phy->hsphy_init_seq;
	}

	if (seq) {
		dev_dbg(uphy->dev, "set param to = 0x%x\n", seq);
		msm_usb_write_readback(phy->base,
				       PARAMETER_OVERRIDE_X_REG(0),
				       0x03FFFFFF, seq & 0x03FFFFFF);
	}
	return 0;
}
static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend)
{
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);
	bool host = uphy->flags & PHY_HOST_MODE;
	bool chg_connected = uphy->flags & PHY_CHARGER_CONNECTED;
	int i, count;

	if (!!suspend == phy->suspended) {
		dev_dbg(uphy->dev, "%s\n", suspend ? "already suspended"
						   : "already resumed");
		return 0;
	}

	if (suspend) {
		for (i = 0; i < phy->num_ports; i++) {
			/* Clear interrupt latch register */
			writel_relaxed(ALT_INTERRUPT_MASK,
				phy->base + HS_PHY_IRQ_STAT_REG(i));

			/* Enable DP and DM HV interrupts */
			if (phy->core_ver >= MSM_CORE_VER_120)
				msm_usb_write_readback(phy->base,
						ALT_INTERRUPT_EN_REG(i),
						(LINESTATE_INTEN |
						DPINTEN | DMINTEN),
						(LINESTATE_INTEN |
						DPINTEN | DMINTEN));
			else
				msm_usb_write_readback(phy->base,
						ALT_INTERRUPT_EN_REG(i),
						DPDMHV_INT_MASK,
						DPDMHV_INT_MASK);
			if (!host) {
				/* set the following:
				 * OTGDISABLE0=1
				 * USB2_SUSPEND_N_SEL=1, USB2_SUSPEND_N=0
				 */
				if (phy->core_ver >= MSM_CORE_VER_120)
					msm_usb_write_readback(phy->base,
							HS_PHY_CTRL_COMMON_REG,
							COMMON_OTGDISABLE0,
							COMMON_OTGDISABLE0);
				else
					msm_usb_write_readback(phy->base,
						HS_PHY_CTRL_REG(i),
						OTGDISABLE0, OTGDISABLE0);

				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(i),
					(USB2_SUSPEND_N_SEL | USB2_SUSPEND_N),
					USB2_SUSPEND_N_SEL);
			}

			if (!phy->ext_vbus_id)
				/* Enable PHY-based IDHV and
				 *OTGSESSVLD HV interrupts
				 */
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(i),
					(OTGSESSVLDHV_INTEN | IDHV_INTEN),
					(OTGSESSVLDHV_INTEN | IDHV_INTEN));
		}

		/* Enable PHY retention */
		if (!host && !chg_connected) {
			if (phy->core_ver == MSM_CORE_VER_120 &&
					phy->set_pllbtune)
				/*
				 * On this particular revision the PLLITUNE[1]
				 * bit acts as the control for the RETENABLEN
				 * PHY signal.
				 */
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_COMMON_REG,
					COMMON_PLLITUNE_1, COMMON_PLLITUNE_1);
			else if (phy->core_ver >= MSM_CORE_VER_120)
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_COMMON_REG,
					COMMON_RETENABLEN, 0);
			else
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(0),
					RETENABLEN, 0);

			if (phy->csr) {
				/* switch PHY control to USB2PHY CSRs */
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_CFG0,
						USB2PHY_OVERRIDE_EN,
						USB2PHY_OVERRIDE_EN);
				/* clear suspend_n */
				msm_usb_write_readback(phy->csr,
						USB2PHY_HS_PHY_CTRL2,
						USB2PHY_SUSPEND_N_SEL |
						USB2PHY_SUSPEND_N,
						USB2PHY_SUSPEND_N_SEL);
				/* enable retention */
				msm_usb_write_readback(phy->csr,
						USB2PHY_HS_PHY_CTRL_COMMON0,
						USB2PHY_COMMONONN |
						USB2PHY_RETENABLEN, 0);
				/* disable internal ref clock buffer */
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_REFCLK_CTRL,
						REFCLK_RXTAP_EN, 0);
				/* power down PHY */
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_PWRDOWN_CTRL,
						PWRDN_B, 0);
			}

			phy->lpm_flags |= PHY_RETENTIONED;
		}

		/* can turn off regulators if disconnected in device mode */
		if (phy->lpm_flags & PHY_RETENTIONED && !phy->cable_connected) {
			if (phy->ext_vbus_id) {
				msm_hsusb_ldo_enable(phy, 0);
				phy->lpm_flags |= PHY_PWR_COLLAPSED;
			}
			msm_hsusb_config_vdd(phy, 0);
		}

		count = atomic_dec_return(&hsphy_active_count);
		if (count < 0) {
			dev_WARN(uphy->dev, "hsphy_active_count=%d, something wrong?\n",
					count);
			atomic_set(&hsphy_active_count, 0);
		}
	} else {
		atomic_inc(&hsphy_active_count);
		if (phy->lpm_flags & PHY_RETENTIONED && !phy->cable_connected) {
			msm_hsusb_config_vdd(phy, 1);
			if (phy->ext_vbus_id) {
				msm_hsusb_ldo_enable(phy, 1);
				phy->lpm_flags &= ~PHY_PWR_COLLAPSED;
			}

			if (phy->csr) {
				/* power on PHY */
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_PWRDOWN_CTRL,
						PWRDN_B, PWRDN_B);
				/* enable internal ref clock buffer */
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_REFCLK_CTRL,
						REFCLK_RXTAP_EN,
						REFCLK_RXTAP_EN);
				/* disable retention */
				msm_usb_write_readback(phy->csr,
						USB2PHY_HS_PHY_CTRL_COMMON0,
						USB2PHY_COMMONONN |
						USB2PHY_RETENABLEN,
						USB2PHY_COMMONONN |
						USB2PHY_RETENABLEN);
				/* switch suspend_n_sel back to HW */
				msm_usb_write_readback(phy->csr,
						USB2PHY_HS_PHY_CTRL2,
						USB2PHY_SUSPEND_N_SEL |
						USB2PHY_SUSPEND_N, 0);
				msm_usb_write_readback(phy->csr,
						USB2PHY_USB_PHY_CFG0,
						USB2PHY_OVERRIDE_EN, 0);
			}

			/* Disable PHY retention */
			if (phy->core_ver == MSM_CORE_VER_120 &&
					phy->set_pllbtune)
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_COMMON_REG,
					COMMON_PLLITUNE_1, 0);
			else if (phy->core_ver >= MSM_CORE_VER_120)
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_COMMON_REG,
					COMMON_RETENABLEN, COMMON_RETENABLEN);
			else
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(0),
					RETENABLEN, RETENABLEN);
			phy->lpm_flags &= ~PHY_RETENTIONED;
		}

		if (phy->core_ver >= MSM_CORE_VER_120) {
			if (phy->set_pllbtune) {
				msm_usb_write_readback(phy->base,
						HS_PHY_CTRL_COMMON_REG,
						FSEL_MASK, 0);
			} else {
				msm_usb_write_readback(phy->base,
						HS_PHY_CTRL_COMMON_REG,
						FSEL_MASK, FSEL_DEFAULT);
			}
		}

		for (i = 0; i < phy->num_ports; i++) {
			if (!phy->ext_vbus_id)
				/* Disable HV interrupts */
				msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(i),
					(OTGSESSVLDHV_INTEN | IDHV_INTEN),
					0);

			/* Clear interrupt latch register */
			writel_relaxed(ALT_INTERRUPT_MASK,
				phy->base + HS_PHY_IRQ_STAT_REG(i));
			/* Disable DP and DM HV interrupt */
			if (phy->core_ver >= MSM_CORE_VER_120)
				msm_usb_write_readback(phy->base,
						ALT_INTERRUPT_EN_REG(i),
						LINESTATE_INTEN, 0);
			else
				msm_usb_write_readback(phy->base,
						ALT_INTERRUPT_EN_REG(i),
						DPDMHV_INT_MASK, 0);
			if (!host) {
				/* Bring PHY out of suspend */
				msm_usb_write_readback(phy->base,
						HS_PHY_CTRL_REG(i),
						USB2_SUSPEND_N_SEL, 0);

				if (phy->core_ver >= MSM_CORE_VER_120)
					msm_usb_write_readback(phy->base,
							HS_PHY_CTRL_COMMON_REG,
							COMMON_OTGDISABLE0,
							0);
				else
					msm_usb_write_readback(phy->base,
							HS_PHY_CTRL_REG(i),
							OTGDISABLE0, 0);
			}
		}
		/*
		 * write HSPHY init value to QSCRATCH reg to set HSPHY
		 * parameters like VBUS valid threshold, disconnect valid
		 * threshold, DC voltage level,preempasis and rise/fall time
		 */
/*++ 2014/11/26 USB Team, PCN00023 ++*/
		if (override_phy_init) {
			phy->hsphy_init_seq = override_phy_init;
			phy->hsphy_host_init_seq = override_phy_init;
		}
		if (!uphy->is_in_host && phy->hsphy_init_seq) {
			printk("[USB] peripheral mode phy setting\n");
			msm_usb_write_readback(phy->base,
					PARAMETER_OVERRIDE_X_REG(0),
					0x03FFFFFF,
					phy->hsphy_init_seq & 0x03FFFFFF);
		}
		if (uphy->is_in_host && phy->hsphy_host_init_seq) {
			printk("[USB] host mode phy setting\n");
			msm_usb_write_readback(phy->base,
					PARAMETER_OVERRIDE_X_REG(0),
					0x03FFFFFF,
					phy->hsphy_host_init_seq & 0x03FFFFFF);
		}
/*-- 2014/11/26 USB Team, PCN00023 --*/
	}

	phy->suspended = !!suspend; /* double-NOT coerces to bool value */
	return 0;
}