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; } }
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"); } }
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; }
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 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; }
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; }
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 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); }
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; }
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; }
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; }
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); }
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; }
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); } }
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; }
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; }
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; }
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; }
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; } }
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; }
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; }
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; }