Beispiel #1
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;
}
Beispiel #2
0
void usb_lpm_exit_w(struct work_struct *work)
{
	struct msmusb_hcd *mhcd = container_of((void *) work,
			struct msmusb_hcd, lpm_exit_work);

	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);

	struct device *dev = container_of((void *)hcd, struct device,
							driver_data);
	msm_xusb_enable_clks(mhcd);


	if (usb_wakeup_phy(hcd)) {
		pr_err("fatal error: cannot bring phy out of lpm\n");
		return;
	}

	/* If resume signalling finishes before lpm exit, PCD is not set in
	 * USBSTS register. Drive resume signal to the downstream device now
	 * so that EHCI can process the upcoming port change interrupt.*/

	writel(readl(USB_PORTSC) | PORTSC_FPR, USB_PORTSC);

	if (mhcd->xceiv && mhcd->xceiv->set_suspend)
		mhcd->xceiv->set_suspend(0);

	if (device_may_wakeup(dev))
		disable_irq_wake(hcd->irq);
	enable_irq(hcd->irq);
}
Beispiel #3
0
void usb_lpm_exit_w(struct work_struct *work)
{
	struct msmusb_hcd *mhcd = container_of((void *) work,
			struct msmusb_hcd, lpm_exit_work);

	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);

	struct device *dev = container_of((void *)hcd, struct device,
							platform_data);
	msm_xusb_enable_clks(mhcd);


	if (usb_wakeup_phy(hcd)) {
		pr_err("fatal error: cannot bring phy out of lpm\n");
		return;
	}

	

	writel(readl(USB_PORTSC) | PORTSC_FPR, USB_PORTSC);

	if (mhcd->xceiv && mhcd->xceiv->set_suspend)
		mhcd->xceiv->set_suspend(mhcd->xceiv, 0);

	if (device_may_wakeup(dev))
		disable_irq_wake(hcd->irq);
	enable_irq(hcd->irq);
}
Beispiel #4
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;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		ret = 0;
	case USB_PHY_SERIAL_PMIC:
		msm_xusb_enable_clks(mhcd);
		writel(0, USB_USBINTR);
#if 0
		ret = msm_fsusb_rpc_init(&mhcd->otg_ops);
		if (!ret)
			msm_fsusb_init_phy();
#endif
		msm_xusb_disable_clks(mhcd);
		break;
	default:
		pr_err("%s: undefined phy type ( %X ) \n", __func__,
						pdata->phy_info);
	}

	return ret;
}
Beispiel #5
0
static void msm_hsusb_request_host(void *handle, int request)
{
	struct msmusb_hcd *mhcd = handle;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;
	struct msm_otg *otg = container_of(mhcd->xceiv, struct msm_otg, otg);

	switch (request) {
	case REQUEST_RESUME:
		usb_hcd_resume_root_hub(hcd);
		break;
	case REQUEST_START:
		if (mhcd->running)
			break;
		wake_lock(&mhcd->wlock);
		msm_xusb_pm_qos_update(mhcd, 1);
		msm_xusb_enable_clks(mhcd);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			if (otg->set_clk)
				otg->set_clk(mhcd->xceiv, 1);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 1);
		if (pdata->config_gpio)
			pdata->config_gpio(1);
		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
		mhcd->running = 1;
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			if (otg->set_clk)
				otg->set_clk(mhcd->xceiv, 0);
		break;
	case REQUEST_STOP:
		if (!mhcd->running)
			break;
		mhcd->running = 0;
		
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_SERIAL_PMIC) {
			usb_lpm_exit(hcd);
			if (cancel_work_sync(&(mhcd->lpm_exit_work)))
				usb_lpm_exit_w(&mhcd->lpm_exit_work);
		}
		usb_remove_hcd(hcd);
		if (pdata->config_gpio)
			pdata->config_gpio(0);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);
		msm_xusb_disable_clks(mhcd);
		wake_lock_timeout(&mhcd->wlock, HZ/2);
		msm_xusb_pm_qos_update(mhcd, 0);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) {
			otg->reset(mhcd->xceiv);
			otg_set_suspend(mhcd->xceiv, 1);
		}
		break;
	}
}
Beispiel #6
0
static void msm_hsusb_request_host(void *handle, int request)
{
	struct msmusb_hcd *mhcd = handle;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	switch (request) {
	case REQUEST_RESUME:
		usb_hcd_resume_root_hub(hcd);
		break;
	case REQUEST_START:
		if (mhcd->running)
			break;
		wake_lock(&mhcd->wlock);
		msm_xusb_pm_qos_update(mhcd, 1);
		msm_xusb_enable_clks(mhcd);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			clk_enable(mhcd->clk);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 1);
		if (pdata->config_gpio)
			pdata->config_gpio(1);
		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
		mhcd->running = 1;
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			clk_disable(mhcd->clk);
		break;
	case REQUEST_STOP:
		if (!mhcd->running)
			break;
		mhcd->running = 0;
		/* come out of lpm before deregistration */
		usb_lpm_exit(hcd);
		if (cancel_work_sync(&(mhcd->lpm_exit_work)))
			usb_lpm_exit_w(&mhcd->lpm_exit_work);
		usb_remove_hcd(hcd);
		if (pdata->config_gpio)
			pdata->config_gpio(0);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);
		msm_xusb_disable_clks(mhcd);
		wake_lock_timeout(&mhcd->wlock, HZ/2);
		msm_xusb_pm_qos_update(mhcd, 0);
		break;
	}
}
static void msm_hsusb_request_host(void *handle, int request)
{
    struct msmusb_hcd *mhcd = handle;
    struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
    struct msm_usb_host_platform_data *pdata = mhcd->pdata;
    struct msm_otg *otg = container_of(mhcd->xceiv, struct msm_otg, phy);
#ifdef CONFIG_USB_OTG
    struct usb_device *udev = hcd->self.root_hub;
#endif
    struct device *dev = hcd->self.controller;

    switch (request) {
#ifdef CONFIG_USB_OTG
    case REQUEST_HNP_SUSPEND:
        /* disable Root hub auto suspend. As hardware is configured
         * for peripheral mode, mark hardware is not available.
         */
        if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) {
            pm_runtime_disable(&udev->dev);
            /* Mark root hub as disconnected. This would
             * protect suspend/resume via sysfs.
             */
            udev->state = USB_STATE_NOTATTACHED;
            clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
            hcd->state = HC_STATE_HALT;
            pm_runtime_put_noidle(dev);
            pm_runtime_suspend(dev);
        }
        break;
    case REQUEST_HNP_RESUME:
        if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) {
            pm_runtime_get_noresume(dev);
            pm_runtime_resume(dev);
            disable_irq(hcd->irq);
            ehci_msm_reset(hcd);
            ehci_msm_run(hcd);
            set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
            pm_runtime_enable(&udev->dev);
            udev->state = USB_STATE_CONFIGURED;
            enable_irq(hcd->irq);
        }
        break;
#endif
    case REQUEST_RESUME:
        usb_hcd_resume_root_hub(hcd);
        break;
    case REQUEST_START:
        if (mhcd->running)
            break;
        pm_runtime_get_noresume(dev);
        pm_runtime_resume(dev);
        wake_lock(&mhcd->wlock);
        msm_xusb_pm_qos_update(mhcd, 1);
        msm_xusb_enable_clks(mhcd);
        if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
            if (otg->set_clk)
                otg->set_clk(mhcd->xceiv, 1);
        if (pdata->vbus_power)
            pdata->vbus_power(pdata->phy_info, 1);
        if (pdata->config_gpio)
            pdata->config_gpio(1);
        usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
        mhcd->running = 1;
        if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
            if (otg->set_clk)
                otg->set_clk(mhcd->xceiv, 0);
        break;
    case REQUEST_STOP:
        if (!mhcd->running)
            break;
        mhcd->running = 0;
        /* come out of lpm before deregistration */
        if (PHY_TYPE(pdata->phy_info) == USB_PHY_SERIAL_PMIC) {
            usb_lpm_exit(hcd);
            if (cancel_work_sync(&(mhcd->lpm_exit_work)))
                usb_lpm_exit_w(&mhcd->lpm_exit_work);
        }
        usb_remove_hcd(hcd);
        if (pdata->config_gpio)
            pdata->config_gpio(0);
        if (pdata->vbus_power)
            pdata->vbus_power(pdata->phy_info, 0);
        msm_xusb_disable_clks(mhcd);
        wake_lock_timeout(&mhcd->wlock, HZ/2);
        msm_xusb_pm_qos_update(mhcd, 0);
        pm_runtime_put_noidle(dev);
        pm_runtime_suspend(dev);
        break;
    }
}