static int dwc_otg_charger_hwdet(bool enable) { int retval; struct usb_phy *phy; struct dwc_otg2 *otg = dwc3_get_otg(); /* Just return if charger detection is not enabled */ if (!charger_detect_enable(otg)) return 0; phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) return -ENODEV; if (enable) { retval = usb_phy_io_write(phy, PWCTRL_HWDETECT, TUSB1211_POWER_CONTROL_SET); if (retval) return retval; otg_dbg(otg, "set HWDETECT\n"); } else { retval = usb_phy_io_write(phy, PWCTRL_HWDETECT, TUSB1211_POWER_CONTROL_CLR); if (retval) return retval; otg_dbg(otg, "clear HWDETECT\n"); } usb_put_phy(phy); return 0; }
/** * omap_usb2_set_comparator - links the comparator present in the sytem with * this phy * @comparator - the companion phy(comparator) for this phy * * The phy companion driver should call this API passing the phy_companion * filled with set_vbus and start_srp to be used by usb phy. * * For use by phy companion driver */ void omap_usb2_set_comparator(struct phy_companion *comparator) { struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); struct omap_usb *phy = phy_to_omapusb(x); phy->comparator = comparator; }
static void usb2phy_eye_optimization(struct dwc_otg2 *otg) { void __iomem *addr; struct usb_phy *phy; struct intel_dwc_otg_pdata *data; if (!otg || !otg->otg_data) return; data = (struct intel_dwc_otg_pdata *)otg->otg_data; phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) return; if ((data->usb2_phy_type == USB2_PHY_ULPI) && !!data->ulpi_eye_calibration) usb_phy_io_write(phy, data->ulpi_eye_calibration, TUSB1211_VENDOR_SPECIFIC1_SET); else if ((data->usb2_phy_type == USB2_PHY_UTMI) && !!data->utmi_eye_calibration) { addr = ioremap_nocache(UTMI_PHY_USB2PERPORT, 4); if (!addr) { otg_info(otg, "UTMI phy register ioremap failed, use default setup!\n"); usb_put_phy(phy); return; } writel(data->utmi_eye_calibration, addr); iounmap(addr); } else otg_info(otg, "usb2 phy eye optimization fail, use default setup!\n"); usb_put_phy(phy); }
static int intel_mid_ehci_driver_register(struct pci_driver *host_driver) { struct usb_phy *otg; struct intel_mid_otg_xceiv *iotg; otg = usb_get_phy(USB_PHY_TYPE_USB2); if (otg == NULL || host_driver == NULL) return -EINVAL; iotg = otg_to_mid_xceiv(otg); iotg->start_host = ehci_mid_start_host; iotg->stop_host = ehci_mid_stop_host; iotg->runtime_suspend_host = ehci_mid_runtime_suspend_host; iotg->runtime_resume_host = ehci_mid_runtime_resume_host; iotg->suspend_host = ehci_mid_suspend_host; iotg->suspend_noirq_host = ehci_mid_suspend_noirq_host; iotg->resume_host = ehci_mid_resume_host; iotg->resume_noirq_host = ehci_mid_resume_noirq_host; /* notify host driver is registered */ atomic_notifier_call_chain(&iotg->iotg_notifier, MID_OTG_NOTIFY_HOSTADD, iotg); usb_put_phy(otg); return 0; }
static int da8xx_musb_init(struct musb *musb) { struct da8xx_glue *glue = dev_get_drvdata(musb->controller->parent); void __iomem *reg_base = musb->ctrl_base; u32 rev; int ret = -ENODEV; musb->mregs += DA8XX_MENTOR_CORE_OFFSET; ret = clk_prepare_enable(glue->clk); if (ret) { dev_err(glue->dev, "failed to enable clock\n"); return ret; } /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); if (!rev) goto fail; musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { ret = -EPROBE_DEFER; goto fail; } setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); /* Reset the controller */ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ ret = phy_init(glue->phy); if (ret) { dev_err(glue->dev, "Failed to init phy.\n"); goto fail; } ret = phy_power_on(glue->phy); if (ret) { dev_err(glue->dev, "Failed to power on phy.\n"); goto err_phy_power_on; } msleep(5); /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ pr_debug("DA8xx OTG revision %08x, control %02x\n", rev, musb_readb(reg_base, DA8XX_USB_CTRL_REG)); musb->isr = da8xx_musb_interrupt; return 0; err_phy_power_on: phy_exit(glue->phy); fail: clk_disable_unprepare(glue->clk); return ret; }
void __init marzen_init_late(void) { /* get usb phy */ phy = usb_get_phy(USB_PHY_TYPE_USB2); shmobile_init_late(); platform_add_devices(marzen_late_devices, ARRAY_SIZE(marzen_late_devices)); }
void __init r8a7779_init_late(void) { /* get USB PHY */ phy = usb_get_phy(USB_PHY_TYPE_USB2); shmobile_init_late(); platform_add_devices(r8a7779_late_devices, ARRAY_SIZE(r8a7779_late_devices)); }
static int ux500_musb_init(struct musb *musb) { musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } return 0; }
/** * omap_usb2_set_comparator - links the comparator present in the sytem with * this phy * @comparator - the companion phy(comparator) for this phy * * The phy companion driver should call this API passing the phy_companion * filled with set_vbus and start_srp to be used by usb phy. * * For use by phy companion driver */ int omap_usb2_set_comparator(struct phy_companion *comparator) { struct omap_usb *phy; struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR(x)) return -ENODEV; phy = phy_to_omapusb(x); phy->comparator = comparator; return 0; }
int omap_usb2_charger_detect(struct phy_companion *comparator) { struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); struct omap_usb *phy = phy_to_omapusb(x); int charger = 0; omap_usb2_suspend(x, 0); charger = omap_usb_charger_detect(phy->control_dev); omap_usb2_suspend(x, 1); return charger; }
static int dsps_musb_init(struct musb *musb) { struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; u32 rev, val; int status; /* mentor core register starts at offset of 0x400 from musb base */ musb->mregs += wrp->musb_core_offset; /* NOP driver needs change if supporting dual instance */ usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) return -ENODEV; /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); if (!rev) { status = -ENODEV; goto err0; } setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb); /* Reset the musb */ dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) data->set_phy_power(1); musb->isr = dsps_interrupt; /* reset the otgdisable bit, needed for host mode to work */ val = dsps_readl(reg_base, wrp->phy_utmi); val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); /* clear level interrupt */ dsps_writel(reg_base, wrp->eoi, 0); return 0; err0: usb_put_phy(musb->xceiv); usb_nop_xceiv_unregister(); return status; }
static int jz4740_musb_init(struct musb *musb) { musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (!musb->xceiv) { pr_err("HS UDC: no transceiver configured\n"); return -ENODEV; } /* Silicon does not implement ConfigData register. * Set dyn_fifo to avoid reading EP config from hardware. */ musb->dyn_fifo = true; musb->isr = jz4740_musb_interrupt; return 0; }
static int usb_otg_suspend(struct usb_hcd *hcd) { struct usb_phy *otg; struct intel_mid_otg_xceiv *iotg; otg = usb_get_phy(USB_PHY_TYPE_USB2); if (otg == NULL) { pr_err("%s: failed to get otg transceiver\n", __func__); return -EINVAL; } iotg = otg_to_mid_xceiv(otg); pr_info("%s: OTG HNP update suspend\n", __func__); atomic_notifier_call_chain(&iotg->iotg_notifier, MID_OTG_NOTIFY_HSUSPEND, iotg); usb_put_phy(otg); return 0; }
static void usb2phy_eye_optimization(struct dwc_otg2 *otg) { struct intel_dwc_otg_pdata *data; struct usb_phy *phy; data = (struct intel_dwc_otg_pdata *)otg->otg_data; phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) return; /* Modify VS1 for better quality in eye diagram */ if (data && data->ti_phy_vs1) usb_phy_io_write(phy, data->ti_phy_vs1, TUSB1211_VENDOR_SPECIFIC1_SET); usb_put_phy(phy); }
static int usb_otg_resume(struct usb_hcd *hcd) { struct usb_phy *otg; struct intel_mid_otg_xceiv *iotg; otg = usb_get_phy(USB_PHY_TYPE_USB2); if (otg == NULL) { pr_err("%s: failed to get otg transceiver\n", __func__); return -EINVAL; } iotg = otg_to_mid_xceiv(otg); dev_dbg(otg->dev, "%s OTG HNP update resume\n", __func__); atomic_notifier_call_chain(&iotg->iotg_notifier, MID_OTG_NOTIFY_HRESUME, iotg); usb_put_phy(otg); return 0; }
static int am35x_musb_init(struct musb *musb) { struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; u32 rev; musb->mregs += USB_MENTOR_CORE_OFFSET; /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, USB_REVISION_REG); if (!rev) return -ENODEV; usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) return -ENODEV; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); /* Reset the musb */ if (data->reset) data->reset(); /* Reset the controller */ musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) data->set_phy_power(1); msleep(5); musb->isr = am35x_musb_interrupt; /* clear level interrupt */ if (data->clear_irq) data->clear_irq(); return 0; }
static int xhci_dwc_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct usb_phy *usb_phy; struct xhci_hcd *xhci = hcd_to_xhci(hcd); usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); otg_set_host(usb_phy->otg, NULL); usb_put_phy(usb_phy); if (xhci) dwc3_stop_host(hcd); usb_put_hcd(hcd); pm_runtime_disable(hcd->self.controller); pm_runtime_set_suspended(hcd->self.controller); wake_lock_destroy(&dwc3_xhci.wakelock); return 0; }
int r8a7778_usb_phy_power(bool enable) { static struct usb_phy *phy = NULL; int ret = 0; if (!phy) phy = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { pr_err("kernel doesn't have usb phy driver\n"); return PTR_ERR(phy); } if (enable) ret = usb_phy_init(phy); else usb_phy_shutdown(phy); return ret; }
static void intel_mid_ehci_driver_unregister(struct pci_driver *host_driver) { struct usb_phy *otg; struct intel_mid_otg_xceiv *iotg; otg = usb_get_phy(USB_PHY_TYPE_USB2); if (otg == NULL) return; iotg = otg_to_mid_xceiv(otg); iotg->start_host = NULL; iotg->stop_host = NULL; iotg->runtime_suspend_host = NULL; iotg->runtime_resume_host = NULL; /* notify host driver is unregistered */ atomic_notifier_call_chain(&iotg->iotg_notifier, MID_OTG_NOTIFY_HOSTREMOVE, iotg); usb_put_phy(otg); }
static int ux500_musb_init(struct musb *musb) { int status; musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } musb->nb.notifier_call = musb_otg_notifications; status = usb_register_notifier(musb->xceiv, &musb->nb); if (status < 0) { dev_dbg(musb->controller, "notification register failed\n"); return status; } musb->isr = ux500_musb_interrupt; return 0; }
static int da8xx_musb_init(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; u32 rev; int ret = -ENODEV; musb->mregs += DA8XX_MENTOR_CORE_OFFSET; /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); if (!rev) goto fail; usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { ret = -EPROBE_DEFER; goto fail; } setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); /* Reset the controller */ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ phy_on(); msleep(5); /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n", rev, __raw_readl(CFGCHIP2), musb_readb(reg_base, DA8XX_USB_CTRL_REG)); musb->isr = da8xx_musb_interrupt; return 0; fail: return ret; }
static int __devinit dwc_otg_driver_probe(struct platform_device *ofdev) { int retval; struct dwc_otg_device *dwc_dev; struct device *dev = &ofdev->dev; struct resource res; ulong gusbcfg_addr; u32 usbcfg = 0; struct resource *nres = 0; #ifdef CONFIG_OF u32 prop; u32 prop_array[15]; #endif dwc_dev = kzalloc(sizeof(*dwc_dev), GFP_KERNEL); if (!dwc_dev) { dev_err(dev, "kmalloc of dwc_otg_device failed\n"); retval = -ENOMEM; goto fail_dwc_dev; } /* Retrieve the memory and IRQ resources. */ dwc_dev->irq = platform_get_irq(ofdev, 0); if (dwc_dev->irq == NO_IRQ) { dev_err(dev, "no device irq\n"); retval = -ENODEV; goto fail_of_irq; } nres = platform_get_resource(ofdev, IORESOURCE_MEM, 0); res = *nres; if(nres == 0) { dev_err(dev, "%s: Can't get USB-OTG register address\n", __func__); retval = -ENOMEM; goto fail_of_irq; } dwc_dev->phys_addr = res.start; dwc_dev->base_len = res.end - res.start + 1; if (!request_mem_region(dwc_dev->phys_addr, dwc_dev->base_len, dwc_driver_name)) { dev_err(dev, "request_mem_region failed\n"); retval = -EBUSY; goto fail_of_irq; } /* Map the DWC_otg Core memory into virtual address space. */ dwc_dev->base = ioremap(platform_get_resource(ofdev, IORESOURCE_MEM, 0)->start, SZ_256K); if (!dwc_dev->base) { dev_err(dev, "ioremap() failed\n"); retval = -ENOMEM; goto fail_ioremap; } dev_dbg(dev, "mapped base=0x%08x\n", (__force u32)dwc_dev->base); /* * Initialize driver data to point to the global DWC_otg * Device structure. */ dev_set_drvdata(dev, dwc_dev);//driver dwc_dev->core_if = dwc_otg_cil_init(dwc_dev->base, &dwc_otg_module_params); if (!dwc_dev->core_if) { dev_err(dev, "CIL initialization failed!\n"); retval = -ENOMEM; goto fail_cil_init; } /* * Set the wqfunc of this core_if as "not set" */ dwc_dev->core_if->wqfunc_setup_done = 0; /* * Validate parameter values after dwc_otg_cil_init. */ if (check_parameters(dwc_dev->core_if)) { retval = -EINVAL; goto fail_check_param; } #ifdef CONFIG_OF if(!of_property_read_u32(ofdev->dev.of_node, "dma-mask", (u32*)&dwc_otg_dma_mask)) { dev->dma_mask = &dwc_otg_dma_mask; } else { dev->dma_mask = NULL; } if(!of_property_read_u32(ofdev->dev.of_node, "ulpi-ddr", &prop)) { dwc_otg_module_params.phy_ulpi_ddr = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-rx-fifo-size", &prop)) { dwc_otg_module_params.host_rx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "dev-rx-fifo-size", &prop)) { dwc_otg_module_params.dev_rx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-nperio-tx-fifo-size", &prop)) { dwc_otg_module_params.host_nperio_tx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "dev-nperio-tx-fifo-size", &prop)) { dwc_otg_module_params.dev_nperio_tx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-perio-tx-fifo-size", &prop)) { dwc_otg_module_params.host_perio_tx_fifo_size = prop; } if(!of_property_read_u32_array(ofdev->dev.of_node, "dev-perio-tx-fifo-size", prop_array, MAX_PERIO_FIFOS)) { int i; for(i=0; i<MAX_PERIO_FIFOS; i++) dwc_otg_module_params.dev_tx_fifo_size[i] = prop_array[i]; } if(!of_property_read_u32_array(ofdev->dev.of_node, "dev-tx-fifo-size", prop_array, MAX_TX_FIFOS)) { int i; for(i=0; i<MAX_TX_FIFOS; i++) dwc_otg_module_params.dev_perio_tx_fifo_size[i] = prop_array[i]; } #endif usb_nop_xceiv_register(); dwc_dev->core_if->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (!dwc_dev->core_if->xceiv) { retval = -ENODEV; goto fail_xceiv; } dwc_set_feature(dwc_dev->core_if); /* Initialize the DWC_otg core. */ dwc_otg_core_init(dwc_dev->core_if); /* * Disable the global interrupt until all the interrupt * handlers are installed. */ spin_lock(&dwc_dev->lock); dwc_otg_disable_global_interrupts(dwc_dev->core_if); spin_unlock(&dwc_dev->lock); /* * Install the interrupt handler for the common interrupts before * enabling common interrupts in core_init below. */ retval = request_irq(dwc_dev->irq, dwc_otg_common_irq, IRQF_SHARED, "dwc_otg", dwc_dev); if (retval) { dev_err(dev, "request of irq%d failed retval: %d\n", dwc_dev->irq, retval); retval = -EBUSY; goto fail_req_irq; } else { dwc_dev->common_irq_installed = 1; } if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { //if (dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) { /* Initialize the PCD */ retval = dwc_otg_pcd_init(dev); if (retval) { dev_err(dev, "dwc_otg_pcd_init failed\n"); dwc_dev->pcd = NULL; goto fail_req_irq; } } gusbcfg_addr = (ulong) (dwc_dev->core_if->core_global_regs) + DWC_GUSBCFG; if (!dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) { //if (dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { /* Initialize the HCD and force_host_mode */ usbcfg = dwc_reg_read(gusbcfg_addr, 0); usbcfg |= DWC_USBCFG_FRC_HST_MODE; dwc_reg_write(gusbcfg_addr, 0, usbcfg); retval = dwc_otg_hcd_init(dev, dwc_dev); if (retval) { dev_err(dev, "dwc_otg_hcd_init failed\n"); dwc_dev->hcd = NULL; goto fail_hcd; } /* configure chargepump interrupt */ dwc_dev->hcd->cp_irq = platform_get_irq_byname(ofdev, "chargepumpirq"); if(dwc_dev->hcd->cp_irq != -ENXIO) { retval = request_irq(dwc_dev->hcd->cp_irq, dwc_otg_externalchgpump_irq, IRQF_SHARED, "dwc_otg_ext_chg_pump", dwc_dev); if (retval) { dev_err(dev, "request of irq failed retval: %d\n", retval); retval = -EBUSY; goto fail_hcd; } else { dev_dbg(dev, "%s: ExtChgPump Detection " "IRQ registered\n", dwc_driver_name); } } } /* * Enable the global interrupt after all the interrupt * handlers are installed. */ dwc_otg_enable_global_interrupts(dwc_dev->core_if); #if 0 usbcfg = dwc_reg_read(gusbcfg_addr, 0); usbcfg &= ~DWC_USBCFG_FRC_HST_MODE; dwc_reg_write(gusbcfg_addr, 0, usbcfg); #endif return 0; fail_hcd: free_irq(dwc_dev->irq, dwc_dev); if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { if (dwc_dev->pcd) dwc_otg_pcd_remove(dev); } fail_req_irq: usb_put_phy(dwc_dev->core_if->xceiv); fail_xceiv: usb_nop_xceiv_unregister(); fail_check_param: dwc_otg_cil_remove(dwc_dev->core_if); fail_cil_init: dev_set_drvdata(dev, NULL); iounmap(dwc_dev->base); fail_ioremap: release_mem_region(dwc_dev->phys_addr, dwc_dev->base_len); fail_of_irq: kfree(dwc_dev); fail_dwc_dev: return retval; }
static int xhci_dwc_drv_probe(struct platform_device *pdev) { struct dwc_otg2 *otg; struct usb_phy *usb_phy; struct dwc_device_par *pdata; struct usb_hcd *hcd; struct resource *res; int retval = 0; int ret; if (usb_disabled()) return -ENODEV; pr_debug("initializing FSL-SOC USB Controller\n"); /* Need platform data for setup */ pdata = (struct dwc_device_par *)pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "No platform data for %s.\n", dev_name(&pdev->dev)); return -ENODEV; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", dev_name(&pdev->dev)); return -ENODEV; } dwc3_xhci.otg_irqnum = res->start; hcd = usb_create_hcd(&xhci_dwc_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; return retval; } hcd->regs = pdata->io_addr; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", dev_name(&pdev->dev)); return -ENODEV; } hcd->rsrc_start = res->start; hcd->rsrc_len = res->end - res->start; usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); if (usb_phy) otg_set_host(usb_phy->otg, &hcd->self); otg = container_of(usb_phy->otg, struct dwc_otg2, otg); if (otg) { otg->start_host = dwc3_start_host; otg->stop_host = dwc3_stop_host; otg->suspend_host = dwc3_suspend_host; otg->resume_host = dwc3_resume_host; } usb_put_phy(usb_phy); /* Enable wakeup irq */ hcd->has_wakeup_irq = 1; INIT_WORK(&dwc3_xhci.reset_hcd, dwc3_host_reset); INIT_WORK(&dwc3_xhci.poll_loopback, dwc3_poll_lp); wake_lock_init(&dwc3_xhci.wakelock, WAKE_LOCK_SUSPEND, "dwc3_host_wakelock"); platform_set_drvdata(pdev, hcd); pm_runtime_no_callbacks(hcd->self.controller); pm_runtime_enable(hcd->self.controller); ret = device_create_file(hcd->self.controller, &dev_attr_host_comp_test); if (ret < 0) dev_err(hcd->self.controller, "Can't register sysfs attribute: %d\n", ret); return retval; }
static int davinci_musb_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; u32 revision; int ret = -ENODEV; usb_nop_xceiv_register(); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { ret = -EPROBE_DEFER; goto unregister; } musb->mregs += DAVINCI_BASE_OFFSET; /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); if (revision == 0) goto fail; setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); davinci_musb_source_power(musb, 0, 1); /* dm355 EVM swaps D+/D- for signal integrity, and * is clocked from the main 24 MHz crystal. */ if (machine_is_davinci_dm355_evm()) { u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); phy_ctrl &= ~(3 << 9); phy_ctrl |= USBPHY_DATAPOL; __raw_writel(phy_ctrl, USB_PHY_CTRL); } /* On dm355, the default-A state machine needs DRVVBUS control. * If we won't be a host, there's no need to turn it on. */ if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); deepsleep &= ~DRVVBUS_FORCE; __raw_writel(deepsleep, DM355_DEEPSLEEP); } /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); /* start the on-chip PHY and its PLL */ phy_on(); msleep(5); /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_musb_interrupt; return 0; fail: usb_put_phy(musb->xceiv); unregister: usb_nop_xceiv_unregister(); return ret; }
static int __devinit isp1704_charger_probe(struct platform_device *pdev) { struct isp1704_charger *isp; int ret = -ENODEV; isp = kzalloc(sizeof *isp, GFP_KERNEL); if (!isp) return -ENOMEM; isp->phy = usb_get_phy(); if (!isp->phy) goto fail0; isp->dev = &pdev->dev; platform_set_drvdata(pdev, isp); isp1704_charger_set_power(isp, 1); ret = isp1704_test_ulpi(isp); if (ret < 0) goto fail1; isp->psy.name = "isp1704"; isp->psy.type = POWER_SUPPLY_TYPE_USB; isp->psy.properties = power_props; isp->psy.num_properties = ARRAY_SIZE(power_props); isp->psy.get_property = isp1704_charger_get_property; ret = power_supply_register(isp->dev, &isp->psy); if (ret) goto fail1; /* * REVISIT: using work in order to allow the usb notifications to be * made atomically in the future. */ INIT_WORK(&isp->work, isp1704_charger_work); isp->nb.notifier_call = isp1704_notifier_call; ret = usb_register_notifier(isp->phy, &isp->nb); if (ret) goto fail2; dev_info(isp->dev, "registered with product id %s\n", isp->model); /* * Taking over the D+ pullup. * * FIXME: The device will be disconnected if it was already * enumerated. The charger driver should be always loaded before any * gadget is loaded. */ if (isp->phy->otg->gadget) usb_gadget_disconnect(isp->phy->otg->gadget); /* Detect charger if VBUS is valid (the cable was already plugged). */ ret = isp1704_read(isp, ULPI_USB_INT_STS); isp1704_charger_set_power(isp, 0); if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { isp->event = USB_EVENT_VBUS; schedule_work(&isp->work); } return 0; fail2: power_supply_unregister(&isp->psy); fail1: usb_put_phy(isp->phy); fail0: kfree(isp); dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); isp1704_charger_set_power(isp, 0); return ret; }
static int pda_power_probe(struct platform_device *pdev) { int ret = 0; dev = &pdev->dev; if (pdev->id != -1) { dev_err(dev, "it's meaningless to register several " "pda_powers; use id = -1\n"); ret = -EINVAL; goto wrongid; } pdata = pdev->dev.platform_data; if (pdata->init) { ret = pdata->init(dev); if (ret < 0) goto init_failed; } ac_draw = regulator_get(dev, "ac_draw"); if (IS_ERR(ac_draw)) { dev_dbg(dev, "couldn't get ac_draw regulator\n"); ac_draw = NULL; } update_status(); update_charger(); if (!pdata->wait_for_status) pdata->wait_for_status = 500; if (!pdata->wait_for_charger) pdata->wait_for_charger = 500; if (!pdata->polling_interval) pdata->polling_interval = 2000; if (!pdata->ac_max_uA) pdata->ac_max_uA = 500000; setup_timer(&charger_timer, charger_timer_func, 0); setup_timer(&supply_timer, supply_timer_func, 0); ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac"); usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb"); if (pdata->supplied_to) { pda_psy_ac.supplied_to = pdata->supplied_to; pda_psy_ac.num_supplicants = pdata->num_supplicants; pda_psy_usb.supplied_to = pdata->supplied_to; pda_psy_usb.num_supplicants = pdata->num_supplicants; } #if IS_ENABLED(CONFIG_USB_PHY) transceiver = usb_get_phy(USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(transceiver)) { if (!pdata->is_usb_online) pdata->is_usb_online = otg_is_usb_online; if (!pdata->is_ac_online) pdata->is_ac_online = otg_is_ac_online; } #endif if (pdata->is_ac_online) { ret = power_supply_register(&pdev->dev, &pda_psy_ac); if (ret) { dev_err(dev, "failed to register %s power supply\n", pda_psy_ac.name); goto ac_supply_failed; } if (ac_irq) { ret = request_irq(ac_irq->start, power_changed_isr, get_irq_flags(ac_irq), ac_irq->name, &pda_psy_ac); if (ret) { dev_err(dev, "request ac irq failed\n"); goto ac_irq_failed; } } else { polling = 1; } } if (pdata->is_usb_online) { ret = power_supply_register(&pdev->dev, &pda_psy_usb); if (ret) { dev_err(dev, "failed to register %s power supply\n", pda_psy_usb.name); goto usb_supply_failed; } if (usb_irq) { ret = request_irq(usb_irq->start, power_changed_isr, get_irq_flags(usb_irq), usb_irq->name, &pda_psy_usb); if (ret) { dev_err(dev, "request usb irq failed\n"); goto usb_irq_failed; } } else { polling = 1; } } #if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) { otg_nb.notifier_call = otg_handle_notification; ret = usb_register_notifier(transceiver, &otg_nb); if (ret) { dev_err(dev, "failure to register otg notifier\n"); goto otg_reg_notifier_failed; } polling = 0; } #endif if (polling) { dev_dbg(dev, "will poll for status\n"); setup_timer(&polling_timer, polling_timer_func, 0); mod_timer(&polling_timer, jiffies + msecs_to_jiffies(pdata->polling_interval)); } if (ac_irq || usb_irq) device_init_wakeup(&pdev->dev, 1); return 0; #if IS_ENABLED(CONFIG_USB_PHY) otg_reg_notifier_failed: if (pdata->is_usb_online && usb_irq) free_irq(usb_irq->start, &pda_psy_usb); #endif usb_irq_failed: if (pdata->is_usb_online) power_supply_unregister(&pda_psy_usb); usb_supply_failed: if (pdata->is_ac_online && ac_irq) free_irq(ac_irq->start, &pda_psy_ac); #if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver)) usb_put_phy(transceiver); #endif ac_irq_failed: if (pdata->is_ac_online) power_supply_unregister(&pda_psy_ac); ac_supply_failed: if (ac_draw) { regulator_put(ac_draw); ac_draw = NULL; } if (pdata->exit) pdata->exit(dev); init_failed: wrongid: return ret; }
static int __init twl4030_bci_probe(struct platform_device *pdev) { struct twl4030_bci *bci; const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; int ret; u32 reg; bci = kzalloc(sizeof(*bci), GFP_KERNEL); if (bci == NULL) return -ENOMEM; if (!pdata) pdata = twl4030_bci_parse_dt(&pdev->dev); bci->dev = &pdev->dev; bci->irq_chg = platform_get_irq(pdev, 0); bci->irq_bci = platform_get_irq(pdev, 1); /* Only proceed further *IF* battery is physically present */ ret = twl4030_is_battery_present(bci); if (ret) { dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret); goto fail_no_battery; } platform_set_drvdata(pdev, bci); bci->ac = power_supply_register(&pdev->dev, &twl4030_bci_ac_desc, NULL); if (IS_ERR(bci->ac)) { ret = PTR_ERR(bci->ac); dev_err(&pdev->dev, "failed to register ac: %d\n", ret); goto fail_register_ac; } bci->usb_reg = regulator_get(bci->dev, "bci3v1"); bci->usb = power_supply_register(&pdev->dev, &twl4030_bci_usb_desc, NULL); if (IS_ERR(bci->usb)) { ret = PTR_ERR(bci->usb); dev_err(&pdev->dev, "failed to register usb: %d\n", ret); goto fail_register_usb; } ret = request_threaded_irq(bci->irq_chg, NULL, twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name, bci); if (ret < 0) { dev_err(&pdev->dev, "could not request irq %d, status %d\n", bci->irq_chg, ret); goto fail_chg_irq; } ret = request_threaded_irq(bci->irq_bci, NULL, twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci); if (ret < 0) { dev_err(&pdev->dev, "could not request irq %d, status %d\n", bci->irq_bci, ret); goto fail_bci_irq; } INIT_WORK(&bci->work, twl4030_bci_usb_work); bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(bci->transceiver)) { bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; usb_register_notifier(bci->transceiver, &bci->usb_nb); } /* Enable interrupts now. */ reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 | TWL4030_TBATOR1 | TWL4030_BATSTS); ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg, TWL4030_INTERRUPTS_BCIIMR1A); if (ret < 0) { dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret); goto fail_unmask_interrupts; } reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV); ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg, TWL4030_INTERRUPTS_BCIIMR2A); if (ret < 0) dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret); twl4030_charger_enable_ac(true); twl4030_charger_enable_usb(bci, true); if (pdata) twl4030_charger_enable_backup(pdata->bb_uvolt, pdata->bb_uamp); else twl4030_charger_enable_backup(0, 0); return 0; fail_unmask_interrupts: if (!IS_ERR_OR_NULL(bci->transceiver)) { usb_unregister_notifier(bci->transceiver, &bci->usb_nb); usb_put_phy(bci->transceiver); } free_irq(bci->irq_bci, bci); fail_bci_irq: free_irq(bci->irq_chg, bci); fail_chg_irq: power_supply_unregister(bci->usb); fail_register_usb: power_supply_unregister(bci->ac); fail_register_ac: fail_no_battery: kfree(bci); return ret; }
static enum power_supply_charger_cable_type dwc3_intel_byt_get_charger_type(struct dwc_otg2 *otg) { struct usb_phy *phy; u8 val, vdat_det, chgd_serx_dm; unsigned long timeout, interval; enum power_supply_charger_cable_type type = POWER_SUPPLY_CHARGER_TYPE_NONE; /* No need to do charger detection if not enabled */ if (!charger_detect_enable(otg)) return POWER_SUPPLY_CHARGER_TYPE_USB_SDP; phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) { otg_err(otg, "Get USB2 PHY failed\n"); return POWER_SUPPLY_CHARGER_TYPE_NONE; } /* PHY Enable: * Power on PHY */ enable_usb_phy(otg, true); /* Wait 10ms (~5ms before PHY de-asserts DIR, * XXus for initial Link reg sync-up).*/ msleep(20); /* DCD Enable: Change OPMODE to 01 (Non-driving), * TermSel to 0, & * XcvrSel to 01 (enable FS xcvr) */ usb_phy_io_write(phy, FUNCCTRL_OPMODE(1) | FUNCCTRL_XCVRSELECT(1), TUSB1211_FUNC_CTRL_SET); usb_phy_io_write(phy, FUNCCTRL_OPMODE(2) | FUNCCTRL_XCVRSELECT(2) | FUNCCTRL_TERMSELECT, TUSB1211_FUNC_CTRL_CLR); /*Enable SW control*/ usb_phy_io_write(phy, PWCTRL_SW_CONTROL, TUSB1211_POWER_CONTROL_SET); /* Enable IDPSRC */ usb_phy_io_write(phy, VS3_CHGD_IDP_SRC_EN, TUSB1211_VENDOR_SPECIFIC3_SET); /* Check DCD result, use same polling parameter */ timeout = jiffies + msecs_to_jiffies(DATACON_TIMEOUT); interval = DATACON_INTERVAL * 1000; /* us */ /* DCD Check: * Delay 66.5 ms. (Note: * TIDP_SRC_ON + TCHGD_SERX_DEB = * 347.8us + 66.1ms). */ usleep_range(66500, 67000); while (!time_after(jiffies, timeout)) { /* Read DP logic level. */ val = usb_phy_io_read(phy, TUSB1211_VENDOR_SPECIFIC4); if (val < 0) { otg_err(otg, "ULPI read error! try again\n"); continue; } if (!(val & VS4_CHGD_SERX_DP)) { otg_info(otg, "Data contact detected!\n"); break; } /* Polling interval */ usleep_range(interval, interval + 2000); } /* Disable DP pullup (Idp_src) */ usb_phy_io_write(phy, VS3_CHGD_IDP_SRC_EN, TUSB1211_VENDOR_SPECIFIC3_CLR); /* SE1 Det Enable: * Read DP/DM logic level. Note: use DEBUG * because VS4 isn’t enabled in this situation. */ val = usb_phy_io_read(phy, TUSB1211_DEBUG); if (val < 0) otg_err(otg, "ULPI read error!\n"); val &= DEBUG_LINESTATE; /* If '11': SE1 detected; goto 'Cleanup'. * Else: goto 'Pri Det Enable'. */ if (val == 3) { type = POWER_SUPPLY_CHARGER_TYPE_SE1; goto cleanup; } /* Pri Det Enable: * Enable VDPSRC. */ usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_SET); /* Wait >106.1ms (40ms for BC * Tvdpsrc_on, 66.1ms for TI CHGD_SERX_DEB). */ msleep(107); /* Pri Det Check: * Check if DM > VDATREF. */ vdat_det = usb_phy_io_read(phy, TUSB1211_POWER_CONTROL); if (vdat_det < 0) otg_err(otg, "ULPI read error!\n"); vdat_det &= PWCTRL_VDAT_DET; /* Check if DM<VLGC */ chgd_serx_dm = usb_phy_io_read(phy, TUSB1211_VENDOR_SPECIFIC4); if (chgd_serx_dm < 0) otg_err(otg, "ULPI read error!\n"); chgd_serx_dm &= VS4_CHGD_SERX_DM; /* If VDAT_DET==0 || CHGD_SERX_DM==1: SDP detected * If VDAT_DET==1 && CHGD_SERX_DM==0: CDP/DCP */ if (vdat_det == 0 || chgd_serx_dm == 1) type = POWER_SUPPLY_CHARGER_TYPE_USB_SDP; /* Disable VDPSRC. */ usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_CLR); /* If SDP, goto “Cleanup”. * Else, goto “Sec Det Enable” */ if (type == POWER_SUPPLY_CHARGER_TYPE_USB_SDP) goto cleanup; /* Sec Det Enable: * delay 1ms. */ usleep_range(1000, 1500); /* Swap DP & DM */ usb_phy_io_write(phy, VS1_DATAPOLARITY, TUSB1211_VENDOR_SPECIFIC1_CLR); /* Enable 'VDMSRC'. */ usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_SET); /* Wait >73ms (40ms for BC Tvdmsrc_on, 33ms for TI TVDPSRC_DEB) */ msleep(80); /* Sec Det Check: * Check if DP>VDATREF. */ val = usb_phy_io_read(phy, TUSB1211_POWER_CONTROL); if (val < 0) otg_err(otg, "ULPI read error!\n"); val &= PWCTRL_VDAT_DET; /* If VDAT_DET==0: CDP detected. * If VDAT_DET==1: DCP detected. */ if (!val) type = POWER_SUPPLY_CHARGER_TYPE_USB_CDP; else type = POWER_SUPPLY_CHARGER_TYPE_USB_DCP; /* Disable VDMSRC. */ usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_CLR); /* Swap DP & DM. */ usb_phy_io_write(phy, VS1_DATAPOLARITY, TUSB1211_VENDOR_SPECIFIC1_SET); cleanup: /* If DCP detected, assert VDPSRC. */ if (type == POWER_SUPPLY_CHARGER_TYPE_USB_DCP) usb_phy_io_write(phy, PWCTRL_SW_CONTROL | PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_SET); usb_put_phy(phy); switch (type) { case POWER_SUPPLY_CHARGER_TYPE_ACA_DOCK: case POWER_SUPPLY_CHARGER_TYPE_ACA_A: case POWER_SUPPLY_CHARGER_TYPE_ACA_B: case POWER_SUPPLY_CHARGER_TYPE_ACA_C: case POWER_SUPPLY_CHARGER_TYPE_USB_DCP: case POWER_SUPPLY_CHARGER_TYPE_USB_CDP: case POWER_SUPPLY_CHARGER_TYPE_SE1: dwc_otg_charger_hwdet(true); break; default: break; }; return type; }
static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = dev_get_platdata(hcd->self.controller); int need_transceiver = (config->otg != 0); int ret; dev_dbg(hcd->self.controller, "starting USB Controller\n"); if (config->otg) { hcd->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ hcd->power_budget = 8; } /* boards can use OTG transceivers in non-OTG modes */ need_transceiver = need_transceiver || machine_is_omap_h2() || machine_is_omap_h3(); /* XXX OMAP16xx only */ if (config->ocpi_enable) config->ocpi_enable(); #ifdef CONFIG_USB_OTG if (need_transceiver) { hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(hcd->phy)) { int status = otg_set_host(hcd->phy->otg, &ohci_to_hcd(ohci)->self); dev_dbg(hcd->self.controller, "init %s phy, status %d\n", hcd->phy->label, status); if (status) { usb_put_phy(hcd->phy); return status; } } else { dev_err(hcd->self.controller, "can't find phy\n"); return -ENODEV; } ohci->start_hnp = start_hnp; } #endif omap_ohci_clock_power(1); if (cpu_is_omap15xx()) { omap_1510_local_bus_power(1); omap_1510_local_bus_init(); } ret = ohci_setup(hcd); if (ret < 0) return ret; if (config->otg || config->rwc) { ohci->hc_control = OHCI_CTRL_RWC; writel(OHCI_CTRL_RWC, &ohci->regs->control); } /* board-specific power switching and overcurrent support */ if (machine_is_omap_osk() || machine_is_omap_innovator()) { u32 rh = roothub_a (ohci); /* power switching (ganged by default) */ rh &= ~RH_A_NPS; /* TPS2045 switch for internal transceiver (port 1) */ if (machine_is_omap_osk()) { ohci_to_hcd(ohci)->power_budget = 250; rh &= ~RH_A_NOCP; /* gpio9 for overcurrent detction */ omap_cfg_reg(W8_1610_GPIO9); gpio_request(9, "OHCI overcurrent"); gpio_direction_input(9); /* for paranoia's sake: disable USB.PUEN */ omap_cfg_reg(W4_USB_HIGHZ); } ohci_writel(ohci, rh, &ohci->regs->roothub.a); ohci->flags &= ~OHCI_QUIRK_HUB_POWER; } else if (machine_is_nokia770()) { /* We require a self-powered hub, which should have * plenty of power. */ ohci_to_hcd(ohci)->power_budget = 0; } /* FIXME khubd hub requests should manage power switching */ omap_ohci_transceiver_power(1); /* board init will have already handled HMC and mux setup. * any external transceiver should already be initialized * too, so all configured ports use the right signaling now. */ return 0; }
/** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ static int dwc3_core_init(struct dwc3 *dwc) { unsigned long timeout; u32 reg; int ret; struct usb_phy *usb_phy; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); /* This should read as U3 followed by revision number */ if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); ret = -ENODEV; goto err0; } dwc->revision = reg; /* issue device SoftReset too */ timeout = jiffies + msecs_to_jiffies(500); dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) break; if (time_after(jiffies, timeout)) { dev_err(dwc->dev, "Reset Timed Out\n"); ret = -ETIMEDOUT; goto err0; } cpu_relax(); } while (true); dwc3_core_soft_reset(dwc); /* DCTL core soft reset may cause PHY hang, delay 1 ms and check ulpi */ mdelay(1); if (!dwc->utmi_phy) { usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); if (usb_phy && usb_phy_io_read(usb_phy, ULPI_VENDOR_ID_LOW) < 0) dev_err(dwc->dev, "ULPI not working after DCTL soft reset\n"); usb_put_phy(usb_phy); } reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: reg &= ~DWC3_GCTL_DSBLCLKGTNG; break; default: dev_dbg(dwc->dev, "No power optimization available\n"); } /* * WORKAROUND: DWC3 revisions <1.90a have a bug * where the device can fail to connect at SuperSpeed * and falls back to high-speed mode which causes * the device to enter a Connect/Disconnect loop */ if (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; dwc3_core_num_eps(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg); return 0; err0: return ret; }