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;
}
Esempio n. 2
0
static int msm_hsphy_notify_connect(struct usb_phy *uphy,
				    enum usb_device_speed speed)
{
	int rc = 0;
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);

	phy->cable_connected = true;

	if (uphy->flags & PHY_HOST_MODE) {
		if (phy->core_ver == MSM_CORE_VER_160 ||
			phy->core_ver == MSM_CORE_VER_161) {
			/* Some snps usb2 picophy revisions require 3.15 V to
			 * operate correctly during full speed host mode at
			 * sub zero temperature.
			 */
			rc = regulator_set_voltage(phy->vdda33,
					USB_HSPHY_3P3_VOL_FSHOST,
					USB_HSPHY_3P3_VOL_MAX);
			if (rc)
				dev_err(phy->phy.dev,
					"unable to set voltage for vdda33\n");
		}
		return 0;
	}

	if (!(uphy->flags & PHY_VBUS_VALID_OVERRIDE))
		return 0;

	/* Set External VBUS Valid Select. Set once, can be left on */
	if (phy->core_ver >= MSM_CORE_VER_120) {
		msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG,
					COMMON_VBUSVLDEXTSEL0,
					COMMON_VBUSVLDEXTSEL0);
	} else {
		msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(0),
					VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
	}

	/* Enable D+ pull-up resistor */
	msm_usb_write_readback(phy->base,
				HS_PHY_CTRL_REG(0),
				VBUSVLDEXT0, VBUSVLDEXT0);

	/* Set OTG VBUS Valid from HSPHY to controller */
	msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0),
				UTMI_OTG_VBUS_VALID,
				UTMI_OTG_VBUS_VALID);

	/* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */
	if (phy->core_ver >= MSM_CORE_VER_120)
		msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0),
					SW_SESSVLD_SEL, SW_SESSVLD_SEL);

	return 0;
}
Esempio n. 3
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);
	}

	msm_hsphy_set_params(uphy);

	return 0;
}
Esempio n. 4
0
static int msm_hsphy_notify_disconnect(struct usb_phy *uphy,
				       enum usb_device_speed speed)
{
	int rc = 0;
	struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy);

	phy->cable_connected = false;

	if (uphy->flags & PHY_HOST_MODE) {
		if (phy->core_ver == MSM_CORE_VER_160 ||
			phy->core_ver == MSM_CORE_VER_161) {
			rc = regulator_set_voltage(phy->vdda33,
					USB_HSPHY_3P3_VOL_MIN,
					USB_HSPHY_3P3_VOL_MAX);
			if (rc)
				dev_err(phy->phy.dev,
					"unable to set voltage for vdda33\n");
		}
		return 0;
	}

	if (!(uphy->flags & PHY_VBUS_VALID_OVERRIDE))
		return 0;

	/* Clear OTG VBUS Valid to Controller */
	msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0),
				UTMI_OTG_VBUS_VALID, 0);

	/* Disable D+ pull-up resistor */
	msm_usb_write_readback(phy->base,
					HS_PHY_CTRL_REG(0), VBUSVLDEXT0, 0);

	/* Indicate value is no longer driven by UTMI_OTG_VBUS_VALID bit */
	if (phy->core_ver >= MSM_CORE_VER_120)
		msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0),
					SW_SESSVLD_SEL, 0);

	return 0;
}
Esempio n. 5
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
		 */
		dev_dbg(uphy->dev, "%s set params\n", __func__);
		msm_hsphy_set_params(uphy);
	}

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