static int omap2430_musb_init(struct musb *musb) { u32 l; int status = 0; struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ if (dev->parent->of_node) musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0); else musb->xceiv = devm_usb_get_phy_dev(dev, 0); if (IS_ERR(musb->xceiv)) { status = PTR_ERR(musb->xceiv); if (status == -ENXIO) return status; pr_err("HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } musb->isr = omap2430_musb_interrupt; status = pm_runtime_get_sync(dev); if (status < 0) { dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); goto err1; } l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ } else { l |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); if (glue->status != OMAP_MUSB_UNKNOWN) omap_musb_set_mailbox(glue); usb_phy_init(musb->xceiv); pm_runtime_put_noidle(musb->controller); return 0; err1: return status; }
static int omap2430_musb_init(struct musb *musb) { u32 l; int status = 0; struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ if (dev->parent->of_node) { musb->phy = devm_phy_get(dev->parent, "usb2-phy"); /* We can't totally remove musb->xceiv as of now because * musb core uses xceiv.state and xceiv.otg. Once we have * a separate state machine to handle otg, these can be moved * out of xceiv and then we can start using the generic PHY * framework */ musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0); } else { musb->xceiv = devm_usb_get_phy_dev(dev, 0); musb->phy = devm_phy_get(dev, "usb"); } if (IS_ERR(musb->xceiv)) { status = PTR_ERR(musb->xceiv); if (status == -ENXIO) return status; dev_dbg(dev, "HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } if (IS_ERR(musb->phy)) { dev_err(dev, "HS USB OTG: no PHY configured\n"); return PTR_ERR(musb->phy); } musb->isr = omap2430_musb_interrupt; phy_init(musb->phy); phy_power_on(musb->phy); l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ } else { l |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, l); dev_dbg(dev, "HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); if (glue->status != MUSB_UNKNOWN) omap_musb_set_mailbox(glue); return 0; }
/** * ehci_hcd_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ static int ehci_hcd_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usbhs_omap_platform_data *pdata = dev->platform_data; struct resource *res; struct usb_hcd *hcd; void __iomem *regs; int ret = -ENODEV; int irq; int i; struct omap_hcd *omap; if (usb_disabled()) return -ENODEV; if (!dev->parent) { dev_err(dev, "Missing parent device\n"); return -ENODEV; } /* For DT boot, get platform data from parent. i.e. usbhshost */ if (dev->of_node) { pdata = dev->parent->platform_data; dev->platform_data = pdata; } if (!pdata) { dev_err(dev, "Missing platform data\n"); return -ENODEV; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "EHCI irq failed\n"); return -ENODEV; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. * Once we have dma capability bindings this can go away. */ if (!dev->dma_mask) dev->dma_mask = &dev->coherent_dma_mask; if (!dev->coherent_dma_mask) dev->coherent_dma_mask = DMA_BIT_MASK(32); hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, dev_name(dev)); if (!hcd) { dev_err(dev, "Failed to create HCD\n"); return -ENOMEM; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = regs; hcd_to_ehci(hcd)->caps = regs; omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; omap->nports = pdata->nports; platform_set_drvdata(pdev, hcd); /* get the PHY devices if needed */ for (i = 0 ; i < omap->nports ; i++) { struct usb_phy *phy; /* get the PHY device */ if (dev->of_node) phy = devm_usb_get_phy_by_phandle(dev, "phys", i); else phy = devm_usb_get_phy_dev(dev, i); if (IS_ERR(phy)) { /* Don't bail out if PHY is not absolutely necessary */ if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) continue; ret = PTR_ERR(phy); dev_err(dev, "Can't get PHY device for port %d: %d\n", i, ret); goto err_phy; } omap->phy[i] = phy; if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) { usb_phy_init(omap->phy[i]); /* bring PHY out of suspend */ usb_phy_set_suspend(omap->phy[i], 0); } } pm_runtime_enable(dev); pm_runtime_get_sync(dev); /* * An undocumented "feature" in the OMAP3 EHCI controller, * causes suspended ports to be taken out of suspend when * the USBCMD.Run/Stop bit is cleared (for example when * we do ehci_bus_suspend). * This breaks suspend-resume if the root-hub is allowed * to suspend. Writing 1 to this undocumented register bit * disables this feature and restores normal behavior. */ ehci_write(regs, EHCI_INSNREG04, EHCI_INSNREG04_DISABLE_UNSUSPEND); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) { dev_err(dev, "failed to add hcd with err %d\n", ret); goto err_pm_runtime; } /* * Bring PHYs out of reset for non PHY modes. * Even though HSIC mode is a PHY-less mode, the reset * line exists between the chips and can be modelled * as a PHY device for reset control. */ for (i = 0; i < omap->nports; i++) { if (!omap->phy[i] || pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) continue; usb_phy_init(omap->phy[i]); /* bring PHY out of suspend */ usb_phy_set_suspend(omap->phy[i], 0); } return 0; err_pm_runtime: pm_runtime_put_sync(dev); err_phy: for (i = 0; i < omap->nports; i++) { if (omap->phy[i]) usb_phy_shutdown(omap->phy[i]); } usb_put_hcd(hcd); return ret; }
static int mv_ehci_probe(struct platform_device *pdev) { struct mv_usb_platform_data *pdata; struct device *dev = &pdev->dev; struct usb_hcd *hcd; struct ehci_hcd *ehci; struct ehci_hcd_mv *ehci_mv; struct resource *r; int retval = -ENODEV; u32 offset; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(&pdev->dev, "failed to allocate memory for platform_data\n"); return -ENODEV; } mv_ehci_dt_parse(pdev, pdata); /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. * Once we have dma capability bindings this can go away. */ if (!dev->dma_mask) dev->dma_mask = &dev->coherent_dma_mask; if (!dev->coherent_dma_mask) dev->coherent_dma_mask = DMA_BIT_MASK(32); if (usb_disabled()) return -ENODEV; hcd = usb_create_hcd(&mv_ehci_hc_driver, &pdev->dev, "mv ehci"); if (!hcd) return -ENOMEM; ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL); if (ehci_mv == NULL) { dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); retval = -ENOMEM; goto err_put_hcd; } platform_set_drvdata(pdev, ehci_mv); ehci_mv->pdata = pdata; ehci_mv->hcd = hcd; ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ehci_mv->clk)) { dev_err(&pdev->dev, "error getting clock\n"); retval = PTR_ERR(ehci_mv->clk); goto err_clear_drvdata; } clk_prepare(ehci_mv->clk); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); retval = -ENODEV; goto err_clear_drvdata; } ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (ehci_mv->cap_regs == NULL) { dev_err(&pdev->dev, "failed to map I/O memory\n"); retval = -EFAULT; goto err_clear_drvdata; } ehci_mv->phy = devm_usb_get_phy_dev(&pdev->dev, MV_USB2_PHY_INDEX); if (IS_ERR_OR_NULL(ehci_mv->phy)) { retval = PTR_ERR(ehci_mv->phy); if (retval != -EPROBE_DEFER && retval != -ENODEV) dev_err(&pdev->dev, "failed to get the outer phy\n"); else { kfree(hcd->bandwidth_mutex); kfree(hcd); return -EPROBE_DEFER; } goto err_clear_drvdata; } retval = mv_ehci_enable(ehci_mv); if (retval) { dev_err(&pdev->dev, "init phy error %d\n", retval); goto err_clear_drvdata; } offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; ehci_mv->op_regs = (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset); hcd->rsrc_start = r->start; hcd->rsrc_len = resource_size(r); hcd->regs = ehci_mv->op_regs; hcd->irq = platform_get_irq(pdev, 0); if (!hcd->irq) { dev_err(&pdev->dev, "Cannot get irq."); retval = -ENODEV; goto err_disable_clk; } ehci = hcd_to_ehci(hcd); ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs; ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { ehci_mv->otg = devm_usb_get_phy_dev(&pdev->dev, MV_USB2_OTG_PHY_INDEX); if (IS_ERR(ehci_mv->otg)) { retval = PTR_ERR(ehci_mv->otg); if (retval == -ENXIO) dev_info(&pdev->dev, "MV_USB_MODE_OTG " "must have CONFIG_USB_PHY enabled\n"); else if (retval != -EPROBE_DEFER) dev_err(&pdev->dev, "unable to find transceiver\n"); goto err_disable_clk; } retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); if (retval < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); retval = -ENODEV; goto err_disable_clk; } /* otg will enable clock before use as host */ mv_ehci_disable(ehci_mv); } else { pxa_usb_extern_call(pdata->id, vbus, set_vbus, 1); retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); if (retval) { dev_err(&pdev->dev, "failed to add hcd with err %d\n", retval); goto err_set_vbus; } } dev_info(&pdev->dev, "successful find EHCI device with regs 0x%p irq %d" " working in %s mode\n", hcd->regs, hcd->irq, ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host"); return 0; err_set_vbus: pxa_usb_extern_call(pdata->id, vbus, set_vbus, 0); err_disable_clk: mv_ehci_disable(ehci_mv); err_clear_drvdata: platform_set_drvdata(pdev, NULL); err_put_hcd: usb_put_hcd(hcd); return retval; }
static int mv_otg_probe(struct platform_device *pdev) { struct mv_usb_platform_data *pdata = pdev->dev.platform_data; struct mv_otg *mvotg; struct usb_otg *otg; struct resource *r; int retval = 0, i; struct device_node *np = pdev->dev.of_node; const __be32 *prop; unsigned int proplen; if (pdata == NULL) { dev_err(&pdev->dev, "failed to get platform data\n"); return -ENODEV; } mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL); if (!mvotg) { dev_err(&pdev->dev, "failed to allocate memory!\n"); return -ENOMEM; } otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); if (!otg) return -ENOMEM; platform_set_drvdata(pdev, mvotg); mvotg->pdev = pdev; mvotg->pdata = pdata; mvotg->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(mvotg->clk)) return PTR_ERR(mvotg->clk); clk_prepare(mvotg->clk); mvotg->qwork = create_singlethread_workqueue("mv_otg_queue"); if (!mvotg->qwork) { dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n"); return -ENOMEM; } INIT_DELAYED_WORK(&mvotg->work, mv_otg_work); /* OTG common part */ mvotg->pdev = pdev; mvotg->phy.dev = &pdev->dev; mvotg->phy.type = USB_PHY_TYPE_USB2; mvotg->phy.otg = otg; mvotg->phy.label = driver_name; mvotg->phy.state = OTG_STATE_UNDEFINED; otg->phy = &mvotg->phy; otg->set_host = mv_otg_set_host; otg->set_peripheral = mv_otg_set_peripheral; otg->set_vbus = mv_otg_set_vbus; mv_otg_phy_bind_device(mvotg); for (i = 0; i < OTG_TIMER_NUM; i++) init_timer(&mvotg->otg_ctrl.timer[i]); r = platform_get_resource(mvotg->pdev, IORESOURCE_MEM, 0); if (r == NULL) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); retval = -ENODEV; goto err_destroy_workqueue; } mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (mvotg->cap_regs == NULL) { dev_err(&pdev->dev, "failed to map I/O memory\n"); retval = -EFAULT; goto err_destroy_workqueue; } mvotg->outer_phy = devm_usb_get_phy_dev(&pdev->dev, MV_USB2_PHY_INDEX); if (IS_ERR_OR_NULL(mvotg->outer_phy)) { retval = PTR_ERR(mvotg->outer_phy); if (retval != -EPROBE_DEFER) dev_err(&pdev->dev, "can not find outer phy\n"); goto err_destroy_workqueue; } /* we will acces controller register, so enable the udc controller */ retval = mv_otg_enable_internal(mvotg); if (retval) { dev_err(&pdev->dev, "mv otg enable error %d\n", retval); goto err_destroy_workqueue; } mvotg->op_regs = (struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs + (readl(mvotg->cap_regs) & CAPLENGTH_MASK)); if (pdata->extern_attr & (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION)) { mvotg->notifier.notifier_call = mv_otg_notifier_callback; pxa_usb_register_notifier(mvotg->pdata->id, &mvotg->notifier); if (pdata->extern_attr & MV_USB_HAS_VBUS_DETECTION) { mvotg->clock_gating = 1; pxa_usb_extern_call(mvotg->pdata->id, vbus, init); } if (pdata->extern_attr & MV_USB_HAS_IDPIN_DETECTION) pxa_usb_extern_call(mvotg->pdata->id, idpin, init); } if (pdata->disable_otg_clock_gating) mvotg->clock_gating = 0; mv_otg_reset(mvotg); mv_otg_init_irq(mvotg); r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0); if (r == NULL) { dev_err(&pdev->dev, "no IRQ resource defined\n"); retval = -ENODEV; goto err_disable_clk; } mvotg->irq = r->start; if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED, driver_name, mvotg)) { dev_err(&pdev->dev, "Request irq %d for OTG failed\n", mvotg->irq); mvotg->irq = 0; retval = -ENODEV; goto err_disable_clk; } retval = usb_add_phy_dev(&mvotg->phy); if (retval < 0) { dev_err(&pdev->dev, "can't register transceiver, %d\n", retval); goto err_disable_clk; } prop = of_get_property(np, "lpm-qos", &proplen); if (!prop) { pr_err("lpm-qos config in DT for mv_otg is not defined\n"); goto err_disable_clk; } else mvotg->lpm_qos = be32_to_cpup(prop); mvotg->qos_idle.name = mvotg->pdev->name; pm_qos_add_request(&mvotg->qos_idle, PM_QOS_CPUIDLE_BLOCK, PM_QOS_CPUIDLE_BLOCK_DEFAULT_VALUE); retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group); if (retval < 0) { dev_dbg(&pdev->dev, "Can't register sysfs attr group: %d\n", retval); goto err_remove_otg_phy; } spin_lock_init(&mvotg->wq_lock); if (spin_trylock(&mvotg->wq_lock)) { mv_otg_run_state_machine(mvotg, 2 * HZ); spin_unlock(&mvotg->wq_lock); } dev_info(&pdev->dev, "successful probe OTG device %s clock gating.\n", mvotg->clock_gating ? "with" : "without"); device_init_wakeup(&pdev->dev, 1); return 0; err_remove_otg_phy: usb_remove_phy(&mvotg->phy); pm_qos_remove_request(&mvotg->qos_idle); err_disable_clk: mv_otg_disable_internal(mvotg); if (pdata->extern_attr & (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION)) pxa_usb_unregister_notifier(mvotg->pdata->id, &mvotg->notifier); err_destroy_workqueue: flush_workqueue(mvotg->qwork); destroy_workqueue(mvotg->qwork); return retval; }