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