static int ehci_msm2_runtime_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	dev_dbg(dev, "EHCI runtime suspend\n");
	return msm_ehci_suspend(mhcd);
}
static void ehci_msm_start_hnp(struct ehci_hcd *ehci)
{
	struct usb_hcd *hcd = ehci_to_hcd(ehci);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	/* OTG driver handles HNP */
	otg_start_hnp(mhcd->xceiv);
}
Esempio n. 3
0
static int __init ehci_msm_probe(struct platform_device *pdev)
{
	struct usb_hcd *hcd;
	struct resource *res;
	struct msm_usb_host_platform_data *pdata;
	int retval;
	struct msmusb_hcd *mhcd;

	hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev, dev_name(&pdev->dev));
	if (!hcd)
		return  -ENOMEM;

	hcd->irq = platform_get_irq(pdev, 0);
	if (hcd->irq < 0) {
		usb_put_hcd(hcd);
		return hcd->irq;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		usb_put_hcd(hcd);
		return -ENODEV;
	}

	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);

	mhcd = hcd_to_mhcd(hcd);
	spin_lock_init(&mhcd->lock);
	mhcd->in_lpm = 0;
	mhcd->running = 0;
	device_init_wakeup(&pdev->dev, 1);

	pdata = pdev->dev.platform_data;
	if (PHY_TYPE(pdata->phy_info) == USB_PHY_UNDEFINED) {
		usb_put_hcd(hcd);
		return -ENODEV;
	}
	hcd->power_budget = pdata->power_budget;
	mhcd->pdata = pdata;
	INIT_WORK(&mhcd->lpm_exit_work, usb_lpm_exit_w);

	wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ, (char *)dev_name(&pdev->dev),
					PM_QOS_DEFAULT_VALUE);

	retval = msm_xusb_init_host(mhcd);

	if (retval < 0) {
		usb_put_hcd(hcd);
		wake_lock_destroy(&mhcd->wlock);
		pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ,
				(char *) dev_name(&pdev->dev));
	}

	return retval;
}
Esempio n. 4
0
static irqreturn_t ehci_msm_irq(struct usb_hcd *hcd)
{
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	if (unlikely(mhcd->in_lpm)) {
		usb_lpm_exit(hcd);
		return IRQ_HANDLED;
	}

	return ehci_irq(hcd);
}
Esempio n. 5
0
static int ehci_msm_bus_resume(struct usb_hcd *hcd)
{
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	usb_lpm_exit(hcd);
	if (cancel_work_sync(&(mhcd->lpm_exit_work)))
		usb_lpm_exit_w(&mhcd->lpm_exit_work);

	return ehci_bus_resume(hcd);

}
Esempio n. 6
0
static int __devexit ehci_msm2_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	msm_ehci_resume(mhcd);
	if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
		pm_runtime_disable(&pdev->dev);
	
	device_init_wakeup(&pdev->dev, 0);
	pm_runtime_set_suspended(&pdev->dev);
	
	if (mhcd->pmic_gpio_dp_irq) {
		if (mhcd->pmic_gpio_dp_irq_enabled)
			disable_irq_wake(mhcd->pmic_gpio_dp_irq);
		free_irq(mhcd->pmic_gpio_dp_irq, mhcd);
	}
	if (mhcd->async_irq) {
		if (mhcd->async_irq_enabled)
			disable_irq_wake(mhcd->async_irq);
		free_irq(mhcd->async_irq, mhcd);
	}

	if (mhcd->wakeup_irq) {
		if (mhcd->wakeup_irq_enabled)
			disable_irq_wake(mhcd->wakeup_irq);
		free_irq(mhcd->wakeup_irq, mhcd);
	}

	if(mhcd->resume_gpio)
		gpio_free(mhcd->resume_gpio);	

	usb_remove_hcd(hcd);

	if (!IS_ERR(mhcd->xo_clk)) {
		clk_disable_unprepare(mhcd->xo_clk);
		clk_put(mhcd->xo_clk);
	} else {
		msm_xo_put(mhcd->xo_handle);
	}
	msm_ehci_vbus_power(mhcd, 0);
	msm_ehci_init_vbus(mhcd, 0);
	msm_ehci_ldo_enable(mhcd, 0);
	msm_ehci_ldo_init(mhcd, 0);
	msm_ehci_init_vddcx(mhcd, 0);

	msm_ehci_init_clocks(mhcd, 0);
	wake_lock_destroy(&mhcd->wlock);
	iounmap(hcd->regs);
	usb_put_hcd(hcd);

	return 0;
}
static void msm_hsusb_start_host(struct usb_bus *bus, int start)
{
    struct usb_hcd *hcd = bus_to_hcd(bus);
    struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

    mhcd->flags = start;
    if (in_interrupt())
        schedule_work(&mhcd->otg_work);
    else
        msm_hsusb_request_host((void *)mhcd, mhcd->flags);

}
Esempio n. 8
0
static int ehci_msm2_pm_suspend(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	dev_dbg(dev, "ehci-msm2 PM suspend\n");

	if (device_may_wakeup(dev))
		enable_irq_wake(hcd->irq);

	return msm_ehci_suspend(mhcd);

}
Esempio n. 9
0
static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
{
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	if (atomic_read(&mhcd->in_lpm)) {
		disable_irq_nosync(hcd->irq);
		mhcd->async_int = true;
		pm_runtime_get(mhcd->dev);
		return IRQ_HANDLED;
	}

	return ehci_irq(hcd);
}
Esempio n. 10
0
static irqreturn_t ehci_msm_irq(struct usb_hcd *hcd)
{
    struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
    struct msm_otg *otg = container_of(mhcd->xceiv, struct msm_otg, phy);

    /*
     * OTG scheduled a work to get Integrated PHY out of LPM,
     * WAIT till then */
    if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED)
        if (atomic_read(&otg->in_lpm))
            return IRQ_HANDLED;

    return ehci_irq(hcd);
}
static int msm_ehci_bus_resume_with_gpio(struct usb_hcd *hcd)
{
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
	int ret;

	gpio_direction_output(mhcd->resume_gpio, 1);

	/* call ehci_bus_resume from ehci-hcd library */
	ret = ehci_bus_resume_func(hcd);

	gpio_direction_output(mhcd->resume_gpio, 0);

	return ret;
}
Esempio n. 12
0
static int msm_ehci_reset(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
	struct msm_usb_host_platform_data *pdata;
	int retval;

	ehci->caps = USB_CAPLENGTH;
	ehci->regs = USB_CAPLENGTH +
		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
	dbg_hcs_params(ehci, "reset");
	dbg_hcc_params(ehci, "reset");

	/* cache the data to minimize the chip reads*/
	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

	hcd->has_tt = 1;
	ehci->sbrn = HCD_USB2;

	retval = ehci_halt(ehci);
	if (retval)
		return retval;

	/* data structure init */
	retval = ehci_init(hcd);
	if (retval)
		return retval;

	retval = ehci_reset(ehci);
	if (retval)
		return retval;

	/* bursts of unspecified length. */
	writel_relaxed(0, USB_AHBBURST);
	/* Use the AHB transactor */
	writel_relaxed(0x08, USB_AHBMODE);
	/* Disable streaming mode and select host mode */
	writel_relaxed(0x13, USB_USBMODE);

	pdata = mhcd->dev->platform_data;
	if (pdata && pdata->use_sec_phy)
		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
								USB_PHY_CTRL2);

	if (pdata && pdata->sw_fpr_ctrl)
		writel_relaxed(readl(USB_GENCONFIG2) | (1<<17), USB_GENCONFIG2);		

	ehci_port_power(ehci, 1);
	return 0;
}
Esempio n. 13
0
static int ehci_msm2_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	if (mhcd->pmic_gpio_dp_irq) {
		if (mhcd->pmic_gpio_dp_irq_enabled)
			disable_irq_wake(mhcd->pmic_gpio_dp_irq);
		free_irq(mhcd->pmic_gpio_dp_irq, mhcd);
	}
	if (mhcd->async_irq) {
		if (mhcd->async_irq_enabled)
			disable_irq_wake(mhcd->async_irq);
		free_irq(mhcd->async_irq, mhcd);
	}

	if (mhcd->wakeup_irq) {
		if (mhcd->wakeup_irq_enabled)
			disable_irq_wake(mhcd->wakeup_irq);
		free_irq(mhcd->wakeup_irq, mhcd);
	}

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

	usb_remove_hcd(hcd);

	if (mhcd->xo_clk) {
		clk_disable_unprepare(mhcd->xo_clk);
		clk_put(mhcd->xo_clk);
	} else {
		msm_xo_put(mhcd->xo_handle);
	}
	msm_ehci_vbus_power(mhcd, 0);
	msm_ehci_init_vbus(mhcd, 0);
	msm_ehci_ldo_enable(mhcd, 0);
	msm_ehci_ldo_init(mhcd, 0);
	msm_ehci_init_vddcx(mhcd, 0);

	msm_ehci_init_clocks(mhcd, 0);
	wakeup_source_trash(&mhcd->ws);
	iounmap(hcd->regs);
	usb_put_hcd(hcd);

#if defined(CONFIG_DEBUG_FS)
	debugfs_remove_recursive(dent_ehci);
#endif
	return 0;
}
Esempio n. 14
0
static void usb_lpm_exit(struct usb_hcd *hcd)
{
	unsigned long flags;
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	spin_lock_irqsave(&mhcd->lock, flags);
	if (!mhcd->in_lpm) {
		spin_unlock_irqrestore(&mhcd->lock, flags);
		return;
	}
	mhcd->in_lpm = 0;
	disable_irq_nosync(hcd->irq);
	schedule_work(&mhcd->lpm_exit_work);
	spin_unlock_irqrestore(&mhcd->lock, flags);
}
Esempio n. 15
0
static int usb_lpm_enter(struct usb_hcd *hcd)
{
	unsigned long flags;
	struct device *dev = container_of((void *)hcd, struct device,
							driver_data);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	spin_lock_irqsave(&mhcd->lock, flags);
	if (mhcd->in_lpm) {
		pr_info("%s: already in lpm. nothing to do\n", __func__);
		spin_unlock_irqrestore(&mhcd->lock, flags);
		return 0;
	}

	if (HC_IS_RUNNING(hcd->state)) {
		pr_info("%s: can't enter into lpm. controller is runnning\n",
			__func__);
		spin_unlock_irqrestore(&mhcd->lock, flags);
		return -1;
	}

	pr_info("%s: lpm enter procedure started\n", __func__);

	mhcd->in_lpm = 1;
	disable_irq(hcd->irq);
	spin_unlock_irqrestore(&mhcd->lock, flags);

	if (usb_suspend_phy(hcd)) {
		mhcd->in_lpm = 0;
		enable_irq(hcd->irq);
		pr_info("phy suspend failed\n");
		pr_info("%s: lpm enter procedure end\n", __func__);
		return -1;
	}

	msm_xusb_disable_clks(mhcd);

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

	if (device_may_wakeup(dev))
		enable_irq_wake(hcd->irq);
	enable_irq(hcd->irq);
	pr_info("%s: lpm enter procedure end\n", __func__);
	return 0;
}
Esempio n. 16
0
static int ehci_msm_bus_resume(struct usb_hcd *hcd)
{
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	wake_lock(&mhcd->wlock);

	if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED) {
		otg_set_suspend(mhcd->xceiv, 0);
	} else { 
		usb_lpm_exit(hcd);
		if (cancel_work_sync(&(mhcd->lpm_exit_work)))
			usb_lpm_exit_w(&mhcd->lpm_exit_work);
	}

	return ehci_bus_resume(hcd);

}
Esempio n. 17
0
static int ehci_msm_bus_suspend(struct usb_hcd *hcd)
{
	int ret;
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);

	ret = ehci_bus_suspend(hcd);
	if (ret) {
		pr_err("ehci_bus suspend faield\n");
		return ret;
	}
	if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED)
		ret = otg_set_suspend(mhcd->xceiv, 1);
	else
		ret = usb_lpm_enter(hcd);

	wake_unlock(&mhcd->wlock);
	return ret;
}
Esempio n. 18
0
static int __exit ehci_msm_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
	int retval = 0;

	device_init_wakeup(&pdev->dev, 0);

	msm_hsusb_request_host((void *)mhcd, REQUEST_STOP);
	msm_xusb_uninit_host(mhcd);
	usb_put_hcd(hcd);
	retval = msm_xusb_rpc_close(mhcd);

	wake_lock_destroy(&mhcd->wlock);
	pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ, (char *) dev_name(&pdev->dev));

	return retval;
}
Esempio n. 19
0
static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
{
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
	int ret = 0;

	if (atomic_read(&mhcd->in_lpm)) {
		dev_dbg(mhcd->dev, "phy async intr\n");
		ret = pm_runtime_get(mhcd->dev);
		if ((ret == 1) || (ret == -EINPROGRESS)) {
			pm_runtime_put_noidle(mhcd->dev);
		} else {
			disable_irq_nosync(hcd->irq);
			mhcd->async_int = true;
		}
		return IRQ_HANDLED;
	}

	return ehci_irq(hcd);
}
Esempio n. 20
0
static int usb_wakeup_phy(struct usb_hcd *hcd)
{
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;
	int ret = -ENODEV;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		break;
	case USB_PHY_SERIAL_PMIC:
		ret = msm_fsusb_resume_phy();
		break;
	default:
		pr_err("%s: undefined phy type ( %X ) \n", __func__,
						pdata->phy_info);
	}

	return ret;
}
Esempio n. 21
0
static int ehci_msm_run(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci  = hcd_to_ehci(hcd);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
	int             retval = 0;
	int     	port   = HCS_N_PORTS(ehci->hcs_params);
	u32 __iomem     *reg_ptr;
	u32             hcc_params;
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	hcd->uses_new_polling = 1;
	hcd->poll_rh = 0;

	USBH_INFO("%s\n", __func__);
	/* set hostmode */
	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
	ehci_writel(ehci, (USBMODE_VBUS | USBMODE_SDIS), reg_ptr);

	/* port configuration - phy, port speed, port power, port enable */
	while (port--)
		ehci_writel(ehci, (PTS_VAL(pdata->phy_info) | PORT_POWER |
				PORT_PE), &ehci->regs->port_status[port]);

	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);

	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
	if (HCC_64BIT_ADDR(hcc_params))
		ehci_writel(ehci, 0, &ehci->regs->segment);

	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
	ehci->command |= CMD_RUN;
	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */

	hcd->state = HC_STATE_RUNNING;

	/*Enable appropriate Interrupts*/
	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);

	return retval;
}
Esempio n. 22
0
static int ehci_msm_bus_resume(struct usb_hcd *hcd)
{
    struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
    struct device *dev = hcd->self.controller;

    wake_lock(&mhcd->wlock);
    pm_runtime_get_noresume(dev);
    pm_runtime_resume(dev);

    if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED) {
        usb_phy_set_suspend(mhcd->xceiv, 0);
    } else { /* PMIC serial phy */
        usb_lpm_exit(hcd);
        if (cancel_work_sync(&(mhcd->lpm_exit_work)))
            usb_lpm_exit_w(&mhcd->lpm_exit_work);
    }

    return ehci_bus_resume(hcd);

}
Esempio n. 23
0
static int ehci_msm_bus_suspend(struct usb_hcd *hcd)
{
    int ret;
    struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
    struct device *dev = hcd->self.controller;

    ret = ehci_bus_suspend(hcd);
    if (ret) {
        pr_err("ehci_bus suspend faield\n");
        return ret;
    }
    if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_INTEGRATED)
        ret = usb_phy_set_suspend(mhcd->xceiv, 1);
    else
        ret = usb_lpm_enter(hcd);

    pm_runtime_put_noidle(dev);
    pm_runtime_suspend(dev);
    wake_unlock(&mhcd->wlock);
    return ret;
}
Esempio n. 24
0
static int ehci_msm2_pm_resume(struct device *dev)
{
	int ret;
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	dev_dbg(dev, "ehci-msm2 PM resume\n");

	if (device_may_wakeup(dev))
		disable_irq_wake(hcd->irq);

	ret = msm_ehci_resume(mhcd);
	if (ret)
		return ret;

	/* Bring the device to full powered state upon system resume */
	pm_runtime_disable(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);

	return 0;
}
Esempio n. 25
0
static int __exit ehci_msm_remove(struct platform_device *pdev)
{
    struct usb_hcd *hcd = platform_get_drvdata(pdev);
    struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
    struct msm_usb_host_platform_data *pdata;
    int retval = 0;

    pdata = pdev->dev.platform_data;
    device_init_wakeup(&pdev->dev, 0);

    msm_hsusb_request_host((void *)mhcd, REQUEST_STOP);
    msm_xusb_uninit_host(mhcd);
    retval = msm_xusb_rpc_close(mhcd);

    wake_lock_destroy(&mhcd->wlock);
    usb_put_hcd(hcd);
    clk_put(pdata->ebi1_clk);

    pm_runtime_disable(&pdev->dev);
    pm_runtime_set_suspended(&pdev->dev);

    return retval;
}
static int __devexit ehci_msm2_remove(struct platform_device *pdev)
{
	struct msm_usb_host_platform_data *pdata;
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct msm_hcd *mhcd = hcd_to_mhcd(hcd);

	pdata = mhcd->dev->platform_data;
	if (mhcd->pmic_gpio_dp_irq) {
		if (mhcd->pmic_gpio_dp_irq_enabled)
			disable_irq_wake(mhcd->pmic_gpio_dp_irq);
		free_irq(mhcd->pmic_gpio_dp_irq, mhcd);
	} else if (pdata->mpm_xo_wakeup_int) {
		msm_mpm_set_pin_wake(pdata->mpm_xo_wakeup_int, 0);
		msm_mpm_enable_pin(pdata->mpm_xo_wakeup_int, 0);
	}
	device_init_wakeup(&pdev->dev, 0);
	pm_runtime_set_suspended(&pdev->dev);

	usb_remove_hcd(hcd);

	msm_xo_put(mhcd->xo_handle);
	msm_ehci_vbus_power(mhcd, 0);
	msm_ehci_init_vbus(mhcd, 0);
	msm_ehci_ldo_enable(mhcd, 0);
	msm_ehci_ldo_init(mhcd, 0);
	msm_ehci_init_vddcx(mhcd, 0);

	msm_ehci_init_clocks(mhcd, 0);
	wake_lock_destroy(&mhcd->wlock);
	iounmap(hcd->regs);
	usb_put_hcd(hcd);

#if defined(CONFIG_DEBUG_FS)
	debugfs_remove_recursive(dent_ehci);
#endif
	return 0;
}
Esempio n. 27
0
static int __exit ehci_msm_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
	int retval = 0;

	device_init_wakeup(&pdev->dev, 0);

	msm_hsusb_request_host(mhcd, REQUEST_STOP);
	if (mhcd->xceiv && mhcd->xceiv->set_host)
		mhcd->xceiv->set_host(mhcd->xceiv, NULL);
	msm_otg_put_transceiver(mhcd->xceiv);
	iounmap(hcd->regs);
	usb_put_hcd(hcd);
	retval = msm_xusb_rpc_close(mhcd);

	clk_put(mhcd->clk);
	clk_put(mhcd->pclk);

	wake_lock_destroy(&mhcd->wlock);
	pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ, pdev->dev.bus_id);

	return retval;
}
Esempio n. 28
0
static int __init ehci_msm_probe(struct platform_device *pdev)
{
	struct usb_hcd *hcd;
	struct resource *res;
	struct msm_usb_host_platform_data *pdata;
	int retval;
	int id = pdev->id;
	struct msmusb_hcd *mhcd;
	char *usb_clks[] = { "usb_hs_clk", "usb_hs2_clk" };
	char *usb_pclks[] = { "usb_hs_pclk", "usb_hs2_pclk" };


	hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev, pdev->dev.bus_id);
	if (!hcd)
		return  -ENOMEM;

	hcd->irq = platform_get_irq(pdev, 0);
	if (hcd->irq < 0) {
		retval = hcd->irq;
		goto err_free_hcd;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		retval = -ENODEV;
		goto err_free_hcd;
	}

	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);

	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

	if (!hcd->regs) {
		retval = -EFAULT;
		goto err_free_hcd;
	}

	mhcd = hcd_to_mhcd(hcd);

	spin_lock_init(&mhcd->lock);
	mhcd->in_lpm = 0;
	mhcd->running = 0;
	device_init_wakeup(&pdev->dev, 1);

	/* get usb clocks */
	mhcd->clk = clk_get(&pdev->dev, usb_clks[id]);
	if (IS_ERR(mhcd->clk)) {
		retval = -ENODEV;
		goto err_map;
	}

	mhcd->pclk = clk_get(&pdev->dev, usb_pclks[id]);
	if (IS_ERR(mhcd->pclk)) {
		retval = -ENODEV;
		goto err_map;
	}

	pdata = pdev->dev.platform_data;
	if (PHY_TYPE(pdata->phy_info) == USB_PHY_UNDEFINED) {
		retval = -ENODEV;
		goto err_map;
	}
	mhcd->pdata = pdata;
	INIT_WORK(&mhcd->lpm_exit_work, usb_lpm_exit_w);

	wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, pdev->dev.bus_id);
	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ, pdev->dev.bus_id,
					PM_QOS_DEFAULT_VALUE);

	/* Register with otg driver. If registration fails, start usb host */
	mhcd->otg_ops.request = msm_hsusb_request_host;
	mhcd->otg_ops.handle = (void *) mhcd;
	retval = msm_xusb_otg_register(mhcd);
	if (retval < 0)
		goto err_map;

	return retval;

err_map:
	iounmap(hcd->regs);
err_free_hcd:
	usb_put_hcd(hcd);
	return retval;
}
Esempio n. 29
0
static int ehci_msm_run(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci  = hcd_to_ehci(hcd);
	struct msmusb_hcd *mhcd = hcd_to_mhcd(hcd);
	int             retval = 0;
	int     	port   = HCS_N_PORTS(ehci->hcs_params);
	u32 __iomem     *reg_ptr;
	u32             hcc_params;
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	hcd->uses_new_polling = 1;
	hcd->poll_rh = 0;

	/* set hostmode */
	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
	ehci_writel(ehci, (USBMODE_VBUS | USBMODE_SDIS), reg_ptr);

	/* port configuration - phy, port speed, port power, port enable */
	while (port--)
		ehci_writel(ehci, (PTS_VAL(pdata->phy_info) | PORT_POWER |
				PORT_PE), &ehci->regs->port_status[port]);

	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);

	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
	if (HCC_64BIT_ADDR(hcc_params))
		ehci_writel(ehci, 0, &ehci->regs->segment);

	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
	ehci->command |= CMD_RUN;
	ehci_writel(ehci, ehci->command, &ehci->regs->command);

	/*
	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
	 * are explicitly handed to companion controller(s), so no TT is
	 * involved with the root hub.  (Except where one is integrated,
	 * and there's no companion controller unless maybe for USB OTG.)
	 *
	 * Turning on the CF flag will transfer ownership of all ports
	 * from the companions to the EHCI controller.  If any of the
	 * companions are in the middle of a port reset at the time, it
	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
	 * guarantees that no resets are in progress.  After we set CF,
	 * a short delay lets the hardware catch up; new resets shouldn't
	 * be started before the port switching actions could complete.
	 */

	down_write(&ehci_cf_port_reset_rwsem);
	hcd->state = HC_STATE_RUNNING;
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
	msleep(5);
	up_write(&ehci_cf_port_reset_rwsem);

	/*Enable appropriate Interrupts*/
	ehci_writel(ehci, INTR_MASK,
			&ehci->regs->intr_enable);

	return retval;
}
Esempio n. 30
0
static int __devinit ehci_msm2_probe(struct platform_device *pdev)
{
	struct usb_hcd *hcd;
	struct resource *res;
	struct msm_hcd *mhcd;
	const struct msm_usb_host_platform_data *pdata;
	char pdev_name[PDEV_NAME_LEN];
	int ret;

	dev_dbg(&pdev->dev, "ehci_msm2 probe\n");

	hcd = usb_create_hcd(&msm_hc2_driver, &pdev->dev,
				dev_name(&pdev->dev));
	if (!hcd) {
		dev_err(&pdev->dev, "Unable to create HCD\n");
		return  -ENOMEM;
	}

	hcd->irq = platform_get_irq(pdev, 0);
	if (hcd->irq < 0) {
		dev_err(&pdev->dev, "Unable to get IRQ resource\n");
		ret = hcd->irq;
		goto put_hcd;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "Unable to get memory resource\n");
		ret = -ENODEV;
		goto put_hcd;
	}

	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);
	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
	if (!hcd->regs) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto put_hcd;
	}

	mhcd = hcd_to_mhcd(hcd);
	mhcd->dev = &pdev->dev;

	snprintf(pdev_name, PDEV_NAME_LEN, "%s.%d", pdev->name, pdev->id);
	mhcd->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, pdev_name);
	if (IS_ERR(mhcd->xo_handle)) {
		dev_err(&pdev->dev, "%s not able to get the handle "
			"to vote for TCXO D0 buffer\n", __func__);
		ret = PTR_ERR(mhcd->xo_handle);
		goto unmap;
	}

	ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
	if (ret) {
		dev_err(&pdev->dev, "%s failed to vote for TCXO "
			"D0 buffer%d\n", __func__, ret);
		goto free_xo_handle;
	}

	ret = msm_ehci_init_clocks(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "unable to initialize clocks\n");
		ret = -ENODEV;
		goto devote_xo_handle;
	}

	ret = msm_ehci_init_vddcx(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "unable to initialize VDDCX\n");
		ret = -ENODEV;
		goto deinit_clocks;
	}

	ret = msm_ehci_config_vddcx(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
		goto deinit_vddcx;
	}

	ret = msm_ehci_ldo_init(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
		goto deinit_vddcx;
	}

	ret = msm_ehci_ldo_enable(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
		goto deinit_ldo;
	}

	ret = msm_ehci_init_vbus(mhcd, 1);
	if (ret) {
		dev_err(&pdev->dev, "unable to get vbus\n");
		goto disable_ldo;
	}

	ret = msm_hsusb_reset(mhcd);
	if (ret) {
		dev_err(&pdev->dev, "hsusb PHY initialization failed\n");
		goto vbus_deinit;
	}

	ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
	if (ret) {
		dev_err(&pdev->dev, "unable to register HCD\n");
		goto vbus_deinit;
	}

	pdata = mhcd->dev->platform_data;
	if (pdata && (!pdata->dock_connect_irq ||
				!irq_read_line(pdata->dock_connect_irq)))
		msm_ehci_vbus_power(mhcd, 1);

	device_init_wakeup(&pdev->dev, 1);
	wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
	wake_lock(&mhcd->wlock);
	INIT_WORK(&mhcd->phy_susp_fail_work, msm_ehci_phy_susp_fail_work);
	/*
	 * This pdev->dev is assigned parent of root-hub by USB core,
	 * hence, runtime framework automatically calls this driver's
	 * runtime APIs based on root-hub's state.
	 */
	/* configure pmic_gpio_irq for D+ change */
	if (pdata && pdata->pmic_gpio_dp_irq)
		mhcd->pmic_gpio_dp_irq = pdata->pmic_gpio_dp_irq;
	if (mhcd->pmic_gpio_dp_irq) {
		ret = request_threaded_irq(mhcd->pmic_gpio_dp_irq, NULL,
				msm_ehci_host_wakeup_irq,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"msm_ehci_host_wakeup", mhcd);
		if (!ret) {
			disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
		} else {
			dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
					mhcd->pmic_gpio_dp_irq, ret);
			mhcd->pmic_gpio_dp_irq = 0;
		}
	}
	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);

	//ASUS_BSP+++ BennyCheng "implement ehci3 phy power collapse mode"
	the_msm_hcd = mhcd;
	usb_ehci_phy_power_control(0);

	mutex_init(&mhcd->ehci_mutex);
	//ASUS_BSP--- BennyCheng "implement ehci3 phy power collapse mode"

	return 0;

vbus_deinit:
	msm_ehci_init_vbus(mhcd, 0);
disable_ldo:
	msm_ehci_ldo_enable(mhcd, 0);
deinit_ldo:
	msm_ehci_ldo_init(mhcd, 0);
deinit_vddcx:
	msm_ehci_init_vddcx(mhcd, 0);
deinit_clocks:
	msm_ehci_init_clocks(mhcd, 0);
devote_xo_handle:
	msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
free_xo_handle:
	msm_xo_put(mhcd->xo_handle);
unmap:
	iounmap(hcd->regs);
put_hcd:
	usb_put_hcd(hcd);

	return ret;
}