Пример #1
0
static void msm_chg_block_off(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 func_ctrl, chg_det;

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED_PHY:
		chg_det = ulpi_read(phy, 0x34);
		/* Turn off charger block */
		chg_det |= ~(1 << 1);
		ulpi_write(phy, chg_det, 0x34);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		/* Clear charger detecting control bits */
		ulpi_write(phy, 0x3F, 0x86);
		/* Clear alt interrupt latch and enable bits */
		ulpi_write(phy, 0x1F, 0x92);
		ulpi_write(phy, 0x1F, 0x95);
		break;
	default:
		break;
	}

	/* put the controller in normal mode */
	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
}
Пример #2
0
static int ulpi_read_id(struct ulpi *ulpi)
{
	int ret;

	/* Test the interface */
	ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
	if (ret < 0)
		goto err;

	ret = ulpi_read(ulpi, ULPI_SCRATCH);
	if (ret < 0)
		return ret;

	if (ret != 0xaa)
		goto err;

	ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW);
	ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8;

	ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
	ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;

	/* Some ULPI devices don't have a vendor id so rely on OF match */
	if (ulpi->id.vendor == 0)
		goto err;

	request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);
	return 0;
err:
	of_device_request_module(&ulpi->dev);
	return 0;
}
Пример #3
0
static void msm_chg_block_on(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 func_ctrl, chg_det;

	/* put the controller in non-driving mode */
	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED_PHY:
		chg_det = ulpi_read(phy, 0x34);
		/* control chg block via ULPI */
		chg_det &= ~(1 << 3);
		ulpi_write(phy, chg_det, 0x34);
		/* Turn on chg detect block */
		chg_det &= ~(1 << 1);
		ulpi_write(phy, chg_det, 0x34);
		udelay(20);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		/* Clear charger detecting control bits */
		ulpi_write(phy, 0x3F, 0x86);
		/* Clear alt interrupt latch and enable bits */
		ulpi_write(phy, 0x1F, 0x92);
		ulpi_write(phy, 0x1F, 0x95);
		udelay(100);
		break;
	default:
		break;
	}
}
Пример #4
0
static void msm_otg_host_phy_tune(struct msm_otg *otg,
		u32 paramb, u32 paramc)
{
	ulpi_write(&otg->phy, paramb, 0x81);
	ulpi_write(&otg->phy, paramc, 0x82);

	pr_info("ULPI 0x%x: 0x%x: 0x%x: 0x%x\n",
			ulpi_read(&otg->phy, 0x80),
			ulpi_read(&otg->phy, 0x81),
			ulpi_read(&otg->phy, 0x82),
			ulpi_read(&otg->phy, 0x83));
	mdelay(100);
}
Пример #5
0
static int usb_suspend_ulpi_phy(struct usb_hcd *hcd)
{
	unsigned long timeout;
	int ret = 0;

	ulpi_read(hcd, 0x14);/* clear PHY interrupt latch register */
	ulpi_write(hcd, 0x08, 0x09);/* turn off PLL on integrated phy */
	ulpi_write(hcd, 0x01, 0x30);/* PHY comparators on in LPM */

	timeout = jiffies + msecs_to_jiffies(500);
	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
	while (!(readl(USB_PORTSC) & PORTSC_PHCD)) {
		if (time_after(jiffies, timeout)) {
			pr_err("%s: Unable to suspend phy\n", __func__);
			ret = -1;
			goto out;
		}
		msleep(1);
	}

	/* block the stp signal */
	writel(readl(USB_USBCMD) | ULPI_STP_CTRL, USB_USBCMD);
	/* enable asynchronous interrupt */
	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL, USB_USBCMD);
out:
	return ret;
}
Пример #6
0
static void target_ulpi_init(void)
{
	unsigned int reg;

	reg = ulpi_read(0x32);
	dprintf(INFO, " Value of ulpi read 0x32 is %08x\n", reg);
	ulpi_write(0x30, 0x32);
	reg = ulpi_read(0x32);
	dprintf(INFO, " Value of ulpi read 0x32 after write is %08x\n", reg);

	reg = ulpi_read(0x36);
	dprintf(INFO, " Value of ulpi read 0x36 is %08x\n", reg);
	ulpi_write(reg | 0x2, 0x36);
	reg = ulpi_read(0x36);
	dprintf(INFO, " Value of ulpi read 0x36 aafter write is %08x\n", reg);
}
Пример #7
0
static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode)
{
	struct tusb1210 *tusb = phy_get_drvdata(phy);
	int ret;

	ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL);
	if (ret < 0)
		return ret;

	switch (mode) {
	case PHY_MODE_USB_HOST:
		ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT
			| ULPI_OTG_CTRL_ID_PULLUP
			| ULPI_OTG_CTRL_DP_PULLDOWN
			| ULPI_OTG_CTRL_DM_PULLDOWN);
		ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
		ret |= ULPI_OTG_CTRL_DRVVBUS;
		break;
	case PHY_MODE_USB_DEVICE:
		ret &= ~(ULPI_OTG_CTRL_DRVVBUS
			 | ULPI_OTG_CTRL_DP_PULLDOWN
			 | ULPI_OTG_CTRL_DM_PULLDOWN);
		ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
		ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT;
		break;
	default:
		/* nothing */
		return 0;
	}

	return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
}
Пример #8
0
static int msm_xusb_init_phy(struct msmusb_hcd *mhcd)
{
	int ret = -ENODEV;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;
	unsigned temp;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		msm_hsusb_rpc_connect();
		/* VBUS might be present. Turn off vbus */
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);
		msm_xusb_enable_clks(mhcd);
		clk_enable(mhcd->clk);
		if (pdata->phy_reset)
			ret = pdata->phy_reset(hcd->regs);
		else
			ret = msm_hsusb_phy_reset();
		if (ret)
			break;
		/* Give some delay to settle phy after reset */
		msleep(100);
		/* Disable VbusValid and SessionEnd comparators */
		ulpi_write(hcd, ULPI_VBUS_VALID
				| ULPI_SESS_END, ULPI_INT_RISE_CLR);
		ulpi_write(hcd, ULPI_VBUS_VALID
				| ULPI_SESS_END, ULPI_INT_FALL_CLR);

		/* set hs driver amplitude to max
		 * to avoid eye diagram failures
		 */
		temp = ulpi_read(hcd, ULPI_CONFIG_REG);
		temp |= ULPI_AMPLITUDE_MAX;
		ulpi_write(hcd, temp, ULPI_CONFIG_REG);

		/* Disable all interrupts */
		writel(0, USB_USBINTR);
		writel(readl(USB_OTGSC) & ~OTGSC_INTR_MASK, USB_OTGSC);
		msm_xusb_disable_clks(mhcd);
		clk_disable(mhcd->clk);
		break;
	case USB_PHY_SERIAL_PMIC:
		msm_xusb_enable_clks(mhcd);
		writel(0, USB_USBINTR);
		ret = msm_fsusb_rpc_init(&mhcd->otg_ops);
		if (!ret)
			msm_fsusb_init_phy();
		msm_xusb_disable_clks(mhcd);
		break;
	default:
		pr_err("%s: undefined phy type ( %X ) \n", __func__,
						pdata->phy_info);
	}

	return ret;
}
Пример #9
0
static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
{
	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
	int val;

	val = ulpi_read(mehci, HSIC_DBG1);
	val &= ~ULPI_MANUAL_ENABLE;
	ulpi_write(mehci, val, HSIC_DBG1);
}
Пример #10
0
static int __devexit msm_otg_remove(struct platform_device *pdev)
{
	struct msm_otg *motg = platform_get_drvdata(pdev);
	struct otg_transceiver *otg = &motg->otg;
	int cnt = 0;

	if (otg->host || otg->gadget)
		return -EBUSY;

	msm_otg_debugfs_cleanup();
	cancel_work_sync(&motg->sm_work);

	msm_otg_resume(motg);

	device_init_wakeup(&pdev->dev, 0);
	pm_runtime_disable(&pdev->dev);

	otg_set_transceiver(NULL);
	free_irq(motg->irq, motg);

	/*
	 * Put PHY in low power mode.
	 */
	ulpi_read(otg, 0x14);
	ulpi_write(otg, 0x08, 0x09);

	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
		if (readl(USB_PORTSC) & PORTSC_PHCD)
			break;
		udelay(1);
		cnt++;
	}
	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
		dev_err(otg->dev, "Unable to suspend PHY\n");

	clk_disable(motg->pclk);
	clk_disable(motg->clk);
	if (motg->core_clk)
		clk_disable(motg->core_clk);

	iounmap(motg->regs);
	pm_runtime_set_suspended(&pdev->dev);

	clk_put(motg->phy_reset_clk);
	clk_put(motg->pclk);
	clk_put(motg->clk);
	if (motg->core_clk)
		clk_put(motg->core_clk);

	kfree(motg);

	return 0;
}
Пример #11
0
static bool msm_chg_check_dcd(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 line_state;
	bool ret = false;

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED_PHY:
		line_state = ulpi_read(phy, 0x15);
		ret = !(line_state & 1);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		line_state = ulpi_read(phy, 0x87);
		ret = line_state & 2;
		break;
	default:
		break;
	}
	return ret;
}
Пример #12
0
static bool msm_chg_check_primary_det(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 chg_det;
	bool ret = false;

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED_PHY:
		chg_det = ulpi_read(phy, 0x34);
		ret = chg_det & (1 << 4);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		chg_det = ulpi_read(phy, 0x87);
		ret = chg_det & 1;
		break;
	default:
		break;
	}
	return ret;
}
Пример #13
0
static int msm_otg_suspend(struct msm_otg *dev)
{
	unsigned long timeout;
	int vbus = 0;

	disable_irq(dev->irq);
	if (atomic_read(&dev->in_lpm))
		goto out;

	ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */
	/* If there is no pmic notify support turn on phy comparators. */
	if (!dev->pmic_notif_supp)
		ulpi_write(dev, 0x01, 0x30);
	ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */

	timeout = jiffies + msecs_to_jiffies(500);
	disable_phy_clk();
	while (!is_phy_clk_disabled()) {
		if (time_after(jiffies, timeout)) {
			pr_err("%s: Unable to suspend phy\n", __func__);
			/* Reset both phy and link */
			otg_reset(dev, 1);
			goto out;
		}
		msleep(1);
	}

	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
	if (dev->hs_pclk)
		clk_disable(dev->hs_pclk);
	if (dev->hs_cclk)
		clk_disable(dev->hs_cclk);
	if (device_may_wakeup(dev->otg.dev)) {
		enable_irq_wake(dev->irq);
		if (dev->vbus_on_irq)
			enable_irq_wake(dev->vbus_on_irq);
	}

	atomic_set(&dev->in_lpm, 1);

	if (!vbus && dev->pmic_notif_supp)
		dev->pdata->pmic_enable_ldo(0);

	pr_info("%s: usb in low power mode\n", __func__);

out:
	enable_irq(dev->irq);

	/* TBD: as there is no bus suspend implemented as of now
	 * it should be dummy check
	 */

	return 0;
}
Пример #14
0
static void target_ulpi_init(void)
{
	unsigned int reg;

	ulpi_read(0x31);
	dprintf(INFO, " Value of ulpi read 0x31 is %08x\n", reg);
	/* todo : the write back value should be calculated according to
	 * reg &= 0xF3 but sometimes the value that is read initially
	 * doesnt look right
	 */
	ulpi_write(0x4A, 0x31);
	reg = ulpi_read(0x31);
	dprintf(INFO, " Value of ulpi read 0x31 after write is %08x\n", reg);

	reg = ulpi_read(0x32);
	dprintf(INFO, " Value of ulpi read 0x32 is %08x\n", reg);
	ulpi_write(0x30, 0x32);
	reg = ulpi_read(0x32);
	dprintf(INFO, " Value of ulpi read 0x32 after write is %08x\n", reg);

	reg = ulpi_read(0x36);
	dprintf(INFO, " Value of ulpi read 0x36 is %08x\n", reg);
	ulpi_write(reg | 0x2, 0x36);
	reg = ulpi_read(0x36);
	dprintf(INFO, " Value of ulpi read 0x36 after write is %08x\n", reg);
}
Пример #15
0
static int ulpi_register(struct device *dev, struct ulpi *ulpi)
{
	int ret;

	/* Test the interface */
	ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
	if (ret < 0)
		return ret;

	ret = ulpi_read(ulpi, ULPI_SCRATCH);
	if (ret < 0)
		return ret;

	if (ret != 0xaa)
		return -ENODEV;

	ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW);
	ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8;

	ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
	ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;

	ulpi->dev.parent = dev;
	ulpi->dev.bus = &ulpi_bus;
	ulpi->dev.type = &ulpi_dev_type;
	dev_set_name(&ulpi->dev, "%s.ulpi", dev_name(dev));

	ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev));

	request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);

	ret = device_register(&ulpi->dev);
	if (ret)
		return ret;

	dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n",
		ulpi->id.vendor, ulpi->id.product);

	return 0;
}
Пример #16
0
static int msm_phy_init(struct usb_phy *phy)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	struct msm_otg_platform_data *pdata = motg->pdata;
	u32 val, ulpi_val = 0;

	/* Program USB PHY Override registers. */
	ulpi_init(motg);

	/*
	 * It is recommended in HPG to reset USB PHY after programming
	 * USB PHY Override registers.
	 */
	msm_phy_reset(motg);

	if (pdata->otg_control == OTG_PHY_CONTROL) {
		val = readl(USB_OTGSC);
		if (pdata->mode == USB_DR_MODE_OTG) {
			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
			val |= OTGSC_IDIE | OTGSC_BSVIE;
		} else if (pdata->mode == USB_DR_MODE_PERIPHERAL) {
			ulpi_val = ULPI_INT_SESS_VALID;
			val |= OTGSC_BSVIE;
		}
		writel(val, USB_OTGSC);
		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
	}

	if (motg->manual_pullup) {
		val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT;
		ulpi_write(phy, val, ULPI_SET(ULPI_MISC_A));

		val = readl(USB_GENCONFIG_2);
		val |= GENCONFIG_2_SESS_VLD_CTRL_EN;
		writel(val, USB_GENCONFIG_2);

		val = readl(USB_USBCMD);
		val |= USBCMD_SESS_VLD_CTRL;
		writel(val, USB_USBCMD);

		val = ulpi_read(phy, ULPI_FUNC_CTRL);
		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
		val |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
		ulpi_write(phy, val, ULPI_FUNC_CTRL);
	}

	if (motg->phy_number)
		writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2);

	return 0;
}
Пример #17
0
static inline void set_driver_amplitude(struct msm_otg *dev)
{
	unsigned res = 0;

	if (!dev->pdata || dev->pdata->drv_ampl == HS_DRV_AMPLITUDE_DEFAULT)
		return;

	res = ulpi_read(dev, ULPI_CONFIG_REG2);
	res &= ~ULPI_DRV_AMPL_MASK;
	if (dev->pdata->drv_ampl != HS_DRV_AMPLITUDE_ZERO_PERCENT)
		res |= dev->pdata->drv_ampl;
	ulpi_write(dev, res, ULPI_CONFIG_REG2);
}
Пример #18
0
static inline void set_pre_emphasis_level(struct msm_otg *dev)
{
	unsigned res = 0;

	if (!dev->pdata || dev->pdata->pemp_level == PRE_EMPHASIS_DEFAULT)
		return;

	res = ulpi_read(dev, ULPI_CONFIG_REG3);
	res &= ~(ULPI_PRE_EMPHASIS_MASK);
	if (dev->pdata->pemp_level != PRE_EMPHASIS_DISABLE)
		res |= dev->pdata->pemp_level;
	ulpi_write(dev, res, ULPI_CONFIG_REG3);
}
Пример #19
0
static void msm_chg_block_on(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 func_ctrl, chg_det;

	/* put the controller in non-driving mode */
	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED
Пример #20
0
static int msm_otg_phy_reset(struct msm_otg *motg)
{
	u32 val;
	int ret;
	int retries;

	ret = msm_otg_link_clk_reset(motg, 1);
	if (ret)
		return ret;
	ret = msm_otg_phy_clk_reset(motg);
	if (ret)
		return ret;
	ret = msm_otg_link_clk_reset(motg, 0);
	if (ret)
		return ret;

	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);

	for (retries = 3; retries > 0; retries--) {
		ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
				ULPI_CLR(ULPI_FUNC_CTRL));
		if (!ret)
			break;
		ret = msm_otg_phy_clk_reset(motg);
		if (ret)
			return ret;
	}
	if (!retries)
		return -ETIMEDOUT;

	/* This reset calibrates the phy, if the above write succeeded */
	ret = msm_otg_phy_clk_reset(motg);
	if (ret)
		return ret;

	for (retries = 3; retries > 0; retries--) {
		ret = ulpi_read(&motg->otg, ULPI_DEBUG);
		if (ret != -ETIMEDOUT)
			break;
		ret = msm_otg_phy_clk_reset(motg);
		if (ret)
			return ret;
	}
	if (!retries)
		return -ETIMEDOUT;

	dev_info(motg->otg.dev, "phy_reset: success\n");
	return 0;
}
Пример #21
0
static inline void set_cdr_auto_reset(struct msm_otg *dev)
{
	unsigned res = 0;

	if (!dev->pdata || dev->pdata->cdr_autoreset == CDR_AUTO_RESET_DEFAULT)
		return;

	res = ulpi_read(dev, ULPI_DIGOUT_CTRL);
	if (dev->pdata->cdr_autoreset == CDR_AUTO_RESET_ENABLE)
		res &=  ~ULPI_CDR_AUTORESET;
	else
		res |=  ULPI_CDR_AUTORESET;
	ulpi_write(dev, res, ULPI_DIGOUT_CTRL);
}
Пример #22
0
static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
{
	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
	int val;

	switch (linestate) {
	case PORT_RESET:
		val = ulpi_read(mehci, HSIC_DBG1);
		val |= ULPI_MANUAL_ENABLE;
		val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
		ulpi_write(mehci, val, HSIC_DBG1);
		break;
	default:
		pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
	}
}
Пример #23
0
static int msm_phy_notify_disconnect(struct usb_phy *phy,
				   enum usb_device_speed speed)
{
	int val;

	/*
	 * Put the transceiver in non-driving mode. Otherwise host
	 * may not detect soft-disconnection.
	 */
	val = ulpi_read(phy, ULPI_FUNC_CTRL);
	val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
	val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
	ulpi_write(phy, val, ULPI_FUNC_CTRL);

	return 0;
}
Пример #24
0
/* If this function returns < 0, the phy reset failed and we cannot
 * continue at this point. The only solution is to wait until the next
 * cable disconnect/reconnect to bring the phy back */
static int usb_phy_reset(struct usb_info *ui)
{
	u32 val;
	int ret;
	int retries;

	if (!ui->phy_reset)
		return 0;

	if (ui->hw_reset)
		ui->hw_reset(1);
	ui->phy_reset();
	if (ui->hw_reset)
		ui->hw_reset(0);

#if defined(CONFIG_ARCH_QSD8X50)
	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);

	/* XXX: only necessary for pre-45nm internal PHYs. */
	for (retries = 3; retries > 0; retries--) {
		ret = ulpi_write(ui, ULPI_FUNC_SUSPENDM, ULPI_FUNC_CTRL_CLR);
		if (!ret)
			break;
		ui->phy_reset();
	}
	if (!retries)
		return -1;

	/* this reset calibrates the phy, if the above write succeeded */
	ui->phy_reset();

	/* XXX: pre-45nm internal phys have a known issue which can cause them
	 * to lockup on reset. If ULPI accesses fail, try resetting the phy
	 * again */
	for (retries = 3; retries > 0; retries--) {
		ret = ulpi_read(ui, ULPI_DEBUG_REG);
		if (ret != 0xffffffff)
			break;
		ui->phy_reset();
	}
	if (!retries)
		return -1;
#endif
	pr_info("msm_hsusb_phy_reset: success\n");
	return 0;
}
Пример #25
0
static int msm_otg_remove(struct platform_device *pdev)
{
	struct msm_otg *motg = platform_get_drvdata(pdev);
	struct usb_phy *phy = &motg->phy;
	int cnt = 0;

	if (phy->otg->host || phy->otg->gadget)
		return -EBUSY;

	msm_otg_debugfs_cleanup();
	cancel_delayed_work_sync(&motg->chg_work);
	cancel_work_sync(&motg->sm_work);

	pm_runtime_resume(&pdev->dev);

	device_init_wakeup(&pdev->dev, 0);
	pm_runtime_disable(&pdev->dev);

	usb_remove_phy(phy);
	disable_irq(motg->irq);

	/*
	 * Put PHY in low power mode.
	 */
	ulpi_read(phy, 0x14);
	ulpi_write(phy, 0x08, 0x09);

	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
		if (readl(USB_PORTSC) & PORTSC_PHCD)
			break;
		udelay(1);
		cnt++;
	}
	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
		dev_err(phy->dev, "Unable to suspend PHY\n");

	clk_disable_unprepare(motg->pclk);
	clk_disable_unprepare(motg->clk);
	if (!IS_ERR(motg->core_clk))
		clk_disable_unprepare(motg->core_clk);
	msm_hsusb_ldo_init(motg, 0);

	pm_runtime_set_suspended(&pdev->dev);

	return 0;
}
Пример #26
0
static unsigned msm_hsusb_ulpi_read_with_reset(void __iomem *usb_base, unsigned reg)
{
	int temp;
	unsigned res;

	for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) {
		res = ulpi_read(usb_base, reg);
		if (res != -1)
			return res;
		msm_hsusb_apps_reset_phy();
	}

	pr_err("%s: ulpi read failed for %d times\n",
			__func__, ULPI_VERIFY_MAX_LOOP_COUNT);

	return -1;
}
Пример #27
0
static int msm_otg_suspend(struct msm_otg *dev)
{
	unsigned long timeout;
	int vbus = 0;

	disable_irq(dev->irq);
	if (dev->in_lpm)
		goto out;

	otg_reset(dev);

	ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */
	ulpi_write(dev, 0x01, 0x30);/* PHY comparators on in LPM */
	ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */

	timeout = jiffies + msecs_to_jiffies(500);
	disable_phy_clk();
	while (!is_phy_clk_disabled()) {
		if (time_after(jiffies, timeout)) {
			pr_err("%s: Unable to suspend phy\n", __func__);
			otg_reset(dev);
			goto out;
		}
		msleep(1);
	}

	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
	clk_disable(dev->clk);
	clk_disable(dev->pclk);
	if (device_may_wakeup(dev->otg.dev))
		enable_irq_wake(dev->irq);
	dev->in_lpm = 1;

	/* TBD: as there is no bus suspend implemented as of now
	 * it should be dummy check
	 */
	if (!vbus || release_wlocks)
		wake_unlock(&dev->wlock);

	pr_info("%s: usb in low power mode\n", __func__);
out:
	enable_irq(dev->irq);

	return 0;
}
Пример #28
0
static int msm_hsusb_phy_verify_access(void __iomem *usb_base)
{
	int temp;

	for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) {
		if (ulpi_read(usb_base, ULPI_DEBUG) != (unsigned)-1)
			break;
		msm_hsusb_apps_reset_phy();
	}

	if (temp == ULPI_VERIFY_MAX_LOOP_COUNT) {
		pr_err("%s: ulpi read failed for %d times\n",
				__func__, ULPI_VERIFY_MAX_LOOP_COUNT);
		return -1;
	}

	return 0;
}
Пример #29
0
static void msm_chg_disable_dcd(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	u32 chg_det;

	switch (motg->pdata->phy_type) {
	case CI_45NM_INTEGRATED_PHY:
		chg_det = ulpi_read(phy, 0x34);
		chg_det &= ~(1 << 5);
		ulpi_write(phy, chg_det, 0x34);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		ulpi_write(phy, 0x10, 0x86);
		break;
	default:
		break;
	}
}
Пример #30
0
static unsigned ulpi_read_with_reset(struct msm_otg *dev, unsigned reg)
{
	int temp;
	unsigned res;

	for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) {
		res = ulpi_read(dev, reg);
		if (res != 0xffffffff)
			return res;

		phy_clk_reset(dev);
	}

	pr_err("%s: ulpi read failed for %d times\n",
			__func__, ULPI_VERIFY_MAX_LOOP_COUNT);

	return -1;
}