コード例 #1
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;
	}
}
コード例 #2
0
static void msm_xusb_uninit_host(struct msmusb_hcd *mhcd)
{
    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:
        if (pdata->vbus_init)
            pdata->vbus_init(0);
        hcd_to_ehci(hcd)->transceiver = NULL;
        otg_set_host(mhcd->xceiv->otg, NULL);
        usb_put_transceiver(mhcd->xceiv);
        cancel_work_sync(&mhcd->otg_work);
        break;
    case USB_PHY_SERIAL_PMIC:
        iounmap(hcd->regs);
        clk_put(mhcd->alt_core_clk);
        clk_put(mhcd->iface_clk);
        msm_fsusb_reset_phy();
        msm_fsusb_rpc_deinit();
        break;
    default:
        pr_err("phy type is bad\n");
    }
}
コード例 #3
0
ファイル: ehci-msm.c プロジェクト: Alex163/htc-kernel-pyramid
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;
}
コード例 #4
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;
	}
}
コード例 #5
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;
}
コード例 #6
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;
}
コード例 #7
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);
}
コード例 #8
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);

}
コード例 #9
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;
}
コード例 #10
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;
}
コード例 #11
0
static int msm_xusb_rpc_close(struct msmusb_hcd *mhcd)
{
	int retval = -ENODEV;
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		if (!mhcd->xceiv)
			retval = msm_hsusb_rpc_close();
		break;
	case USB_PHY_SERIAL_PMIC:
		retval = msm_fsusb_reset_phy();
		msm_fsusb_rpc_deinit();
		break;
	default:
		pr_err("%s: undefined phy type ( %X ) \n", __func__,
						pdata->phy_info);
	}
	return retval;
}
コード例 #12
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);

}
コード例 #13
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;
}
コード例 #14
0
static void msm_xusb_pm_qos_update(struct msmusb_hcd *mhcd, int vote)
{
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);

	if (PHY_TYPE(mhcd->pdata->phy_info) == USB_PHY_SERIAL_PMIC)
		goto vote_for_axi;

	if (!depends_on_axi_freq(mhcd->xceiv))
		return;

vote_for_axi:
	if (vote) {
		pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ,
				(char *)hcd->self.bus_name,
				 MSM_AXI_MAX_FREQ);
	} else {
		pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ,
				(char *) hcd->self.bus_name,
				PM_QOS_DEFAULT_VALUE);
	}
}
コード例 #15
0
static void msm_xusb_enable_clks(struct msmusb_hcd *mhcd)
{
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	if (mhcd->clk_enabled)
		return;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		clk_enable(mhcd->pclk);
		break;
	case USB_PHY_SERIAL_PMIC:
		clk_enable(mhcd->clk);
		clk_enable(mhcd->pclk);
		break;
	default:
		pr_err("%s: undefined phy type ( %X ) \n", __func__,
						pdata->phy_info);
		return;
	}
	mhcd->clk_enabled = 1;
}
コード例 #16
0
static void msm_xusb_enable_clks(struct msmusb_hcd *mhcd)
{
    struct msm_usb_host_platform_data *pdata = mhcd->pdata;

    if (mhcd->clk_enabled)
        return;

    switch (PHY_TYPE(pdata->phy_info)) {
    case USB_PHY_INTEGRATED:
        /* OTG driver takes care of clock management */
        break;
    case USB_PHY_SERIAL_PMIC:
        clk_prepare_enable(mhcd->alt_core_clk);
        clk_prepare_enable(mhcd->iface_clk);
        break;
    default:
        pr_err("%s: undefined phy type ( %X )\n", __func__,
               pdata->phy_info);
        return;
    }
    mhcd->clk_enabled = 1;
}
コード例 #17
0
static int msm_xusb_otg_register(struct msmusb_hcd *mhcd)
{
	int ret = 0;
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		ret = msm_xusb_init_phy(mhcd);
		if (ret)
			break;
		mhcd->xceiv = msm_otg_get_transceiver();
		if (mhcd->xceiv && mhcd->xceiv->set_host)
			mhcd->xceiv->set_host(mhcd->xceiv, &mhcd->otg_ops);
		else
			msm_hsusb_request_host(mhcd, REQUEST_START);
		break;
	case USB_PHY_SERIAL_PMIC:
		msm_xusb_init_phy(mhcd);
		break;
	default:
		pr_err("phy type is bad\n");
	}
	return ret;
}
コード例 #18
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;
}
コード例 #19
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, 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;
    }
}
コード例 #20
0
static int msm_xusb_init_host(struct msmusb_hcd *mhcd)
{
	int ret = 0;
	struct msm_otg *otg;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;
	struct device *dev = container_of((void *)hcd, struct device,
							platform_data);	

	switch (PHY_TYPE(pdata->phy_info)) {
	case USB_PHY_INTEGRATED:
		msm_hsusb_rpc_connect();

		if (pdata->vbus_init)
			pdata->vbus_init(1);

		
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);

		INIT_WORK(&mhcd->otg_work, msm_hsusb_otg_work);
		mhcd->xceiv = otg_get_transceiver();
		if (!mhcd->xceiv)
			return -ENODEV;
		otg = container_of(mhcd->xceiv, struct msm_otg, otg);
		hcd->regs = otg->regs;
		otg->start_host = msm_hsusb_start_host;

		ret = otg_set_host(mhcd->xceiv, &hcd->self);
		break;
	case USB_PHY_SERIAL_PMIC:
		hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

		if (!hcd->regs)
			return -EFAULT;
		
		mhcd->clk = clk_get(dev, "usb_hs2_clk");
		if (IS_ERR(mhcd->clk)) {
			iounmap(hcd->regs);
			return PTR_ERR(mhcd->clk);
		}

		mhcd->pclk = clk_get(dev, "usb_hs2_pclk");
		if (IS_ERR(mhcd->pclk)) {
			iounmap(hcd->regs);
			clk_put(mhcd->clk);
			return PTR_ERR(mhcd->pclk);
		}
		mhcd->otg_ops.request = msm_hsusb_request_host;
		mhcd->otg_ops.handle = (void *) mhcd;
		ret = msm_xusb_init_phy(mhcd);
		if (ret < 0) {
			iounmap(hcd->regs);
			clk_put(mhcd->clk);
			clk_put(mhcd->pclk);
		}
		break;
	default:
		pr_err("phy type is bad\n");
	}
	return ret;
}
コード例 #21
0
static int msm_xusb_init_host(struct platform_device *pdev,
                              struct msmusb_hcd *mhcd)
{
    int ret = 0;
    struct msm_otg *otg;
    struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    struct msm_usb_host_platform_data *pdata = mhcd->pdata;

    switch (PHY_TYPE(pdata->phy_info)) {
    case USB_PHY_INTEGRATED:
        msm_hsusb_rpc_connect();

        if (pdata->vbus_init)
            pdata->vbus_init(1);

        /* VBUS might be present. Turn off vbus */
        if (pdata->vbus_power)
            pdata->vbus_power(pdata->phy_info, 0);

        INIT_WORK(&mhcd->otg_work, msm_hsusb_otg_work);
        mhcd->xceiv = usb_get_transceiver();
        if (!mhcd->xceiv)
            return -ENODEV;
        otg = container_of(mhcd->xceiv, struct msm_otg, phy);
        hcd->regs = otg->regs;
        otg->start_host = msm_hsusb_start_host;

        ret = otg_set_host(mhcd->xceiv->otg, &hcd->self);
        ehci->transceiver = mhcd->xceiv;
        break;
    case USB_PHY_SERIAL_PMIC:
        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

        if (!hcd->regs)
            return -EFAULT;
        /* get usb clocks */
        mhcd->alt_core_clk = clk_get(&pdev->dev, "alt_core_clk");
        if (IS_ERR(mhcd->alt_core_clk)) {
            iounmap(hcd->regs);
            return PTR_ERR(mhcd->alt_core_clk);
        }

        mhcd->iface_clk = clk_get(&pdev->dev, "iface_clk");
        if (IS_ERR(mhcd->iface_clk)) {
            iounmap(hcd->regs);
            clk_put(mhcd->alt_core_clk);
            return PTR_ERR(mhcd->iface_clk);
        }
        mhcd->otg_ops.request = msm_hsusb_request_host;
        mhcd->otg_ops.handle = (void *) mhcd;
        ret = msm_xusb_init_phy(mhcd);
        if (ret < 0) {
            iounmap(hcd->regs);
            clk_put(mhcd->alt_core_clk);
            clk_put(mhcd->iface_clk);
        }
        break;
    default:
        pr_err("phy type is bad\n");
    }
    return ret;
}
コード例 #22
0
static int __devinit 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));
    pdata->ebi1_clk = clk_get(&pdev->dev, "core_clk");
    if (IS_ERR(pdata->ebi1_clk))
        pdata->ebi1_clk = NULL;
    else
        clk_set_rate(pdata->ebi1_clk, INT_MAX);

    retval = msm_xusb_init_host(pdev, mhcd);

    if (retval < 0) {
        wake_lock_destroy(&mhcd->wlock);
        usb_put_hcd(hcd);
        clk_put(pdata->ebi1_clk);
    }

    pm_runtime_enable(&pdev->dev);

    return retval;
}