/* * We need to register our own PCI probe function (instead of the USB core's * function) in order to create a second roothub under xHCI. */ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; struct xhci_hcd *xhci; struct hc_driver *driver; struct usb_hcd *hcd; driver = (struct hc_driver *)id->driver_data; /* Prevent runtime suspending between USB-2 and USB-3 initialization */ pm_runtime_get_noresume(&dev->dev); /* Register the USB 2.0 roothub. * FIXME: USB core must know to register the USB 2.0 roothub first. * This is sort of silly, because we could just set the HCD driver flags * to say USB 2.0, but I'm not sure what the implications would be in * the other parts of the HCD code. */ retval = usb_hcd_pci_probe(dev, id); if (retval) goto put_runtime_pm; /* USB 2.0 roothub is stored in the PCI device now. */ hcd = dev_get_drvdata(&dev->dev); xhci = hcd_to_xhci(hcd); xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, pci_name(dev), hcd); if (!xhci->shared_hcd) { retval = -ENOMEM; goto dealloc_usb2_hcd; } retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED); if (retval) goto put_usb3_hcd; /* Roothub already marked as USB 3.0 speed */ if (!(xhci->quirks & XHCI_BROKEN_STREAMS) && HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_acpi_rtd3_enable(dev); /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */ pm_runtime_put_noidle(&dev->dev); return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_hcd_pci_remove(dev); put_runtime_pm: pm_runtime_put_noidle(&dev->dev); return retval; }
static int xhci_plat_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct clk *clk; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_hc_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; /* Try to set 64-bit DMA first */ if (WARN_ON(!pdev->dev.dma_mask)) /* Platform did not initialize dma_mask */ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); else ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */ if (ret) { ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (ret) return ret; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); /* * Not all platforms have a clk so it is not an error if the * clock does not exists. */ clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk); if (ret) goto put_hcd; } else if (PTR_ERR(clk) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto put_hcd; } xhci = hcd_to_xhci(hcd); match = of_match_node(usb_xhci_of_match, pdev->dev.of_node); if (match) { const struct xhci_plat_priv *priv_match = match->data; struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); /* Just copy data for now */ if (priv_match) *priv = *priv_match; } device_wakeup_enable(hcd->self.controller); xhci->clk = clk; xhci->main_hcd = hcd; xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto disable_clk; } if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) xhci->quirks |= XHCI_LPM_SUPPORT; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); if (IS_ERR(hcd->usb_phy)) { ret = PTR_ERR(hcd->usb_phy); if (ret == -EPROBE_DEFER) goto put_usb3_hcd; hcd->usb_phy = NULL; } else { ret = usb_phy_init(hcd->usb_phy); if (ret) goto put_usb3_hcd; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_usb_phy; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_usb_phy: usb_phy_shutdown(hcd->usb_phy); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); put_hcd: usb_put_hcd(hcd); return ret; }
static int xhci_plat_probe(struct platform_device *pdev) { const struct xhci_plat_priv *priv_match; const struct hc_driver *driver; struct device *sysdev; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct clk *clk; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_hc_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; /* * sysdev must point to a device that is known to the system firmware * or PCI hardware. We handle these three cases here: * 1. xhci_plat comes from firmware * 2. xhci_plat is child of a device from firmware (dwc3-plat) * 3. xhci_plat is grandchild of a pci device (dwc3-pci) */ for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) { if (is_of_node(sysdev->fwnode) || is_acpi_device_node(sysdev->fwnode)) break; #ifdef CONFIG_PCI else if (sysdev->bus == &pci_bus_type) break; #endif } if (!sysdev) sysdev = &pdev->dev; /* Try to set 64-bit DMA first */ if (WARN_ON(!sysdev->dma_mask)) /* Platform did not initialize dma_mask */ ret = dma_coerce_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); else ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */ if (ret) { ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(32)); if (ret) return ret; } pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, dev_name(&pdev->dev), NULL); if (!hcd) { ret = -ENOMEM; goto disable_runtime; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); /* * Not all platforms have a clk so it is not an error if the * clock does not exists. */ clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk); if (ret) goto put_hcd; } else if (PTR_ERR(clk) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto put_hcd; } xhci = hcd_to_xhci(hcd); priv_match = of_device_get_match_data(&pdev->dev); if (priv_match) { struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); /* Just copy data for now */ if (priv_match) *priv = *priv_match; } device_wakeup_enable(hcd->self.controller); xhci->clk = clk; xhci->main_hcd = hcd; xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto disable_clk; } if (device_property_read_bool(sysdev, "usb2-lpm-disable")) xhci->quirks |= XHCI_HW_LPM_DISABLE; if (device_property_read_bool(sysdev, "usb3-lpm-capable")) xhci->quirks |= XHCI_LPM_SUPPORT; if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) xhci->quirks |= XHCI_BROKEN_PORT_PED; /* imod_interval is the interrupt moderation value in nanoseconds. */ xhci->imod_interval = 40000; device_property_read_u32(sysdev, "imod-interval-ns", &xhci->imod_interval); hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0); if (IS_ERR(hcd->usb_phy)) { ret = PTR_ERR(hcd->usb_phy); if (ret == -EPROBE_DEFER) goto put_usb3_hcd; hcd->usb_phy = NULL; } else { ret = usb_phy_init(hcd->usb_phy); if (ret) goto put_usb3_hcd; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_usb_phy; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; device_enable_async_suspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); /* * Prevent runtime pm from being on as default, users should enable * runtime pm using power/control in sysfs. */ pm_runtime_forbid(&pdev->dev); return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_usb_phy: usb_phy_shutdown(hcd->usb_phy); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); put_hcd: usb_put_hcd(hcd); disable_runtime: pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; }
static int xhci_plat_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev); const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct clk *clk; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_hc_driver; #ifdef CONFIG_USB_XHCI_MTK /* device tree support */ irq = platform_get_irq_byname(pdev, XHCI_DRIVER_NAME); if (irq < 0) return -ENODEV; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, XHCI_BASE_REGS_ADDR_RES_NAME); if (!res) return -ENODEV; pdev->dev.coherent_dma_mask = XHCI_DMA_BIT_MASK; pdev->dev.dma_mask = &xhci_dma_mask; pdev->dev.release = xhci_hcd_release; #else irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; #endif /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) return ret; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; else dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_hcd; } /* * Not all platforms have a clk so it is not an error if the * clock does not exists. */ clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk); if (ret) goto put_hcd; } if (of_device_is_compatible(pdev->dev.of_node, "marvell,armada-375-xhci") || of_device_is_compatible(pdev->dev.of_node, "marvell,armada-380-xhci")) { ret = xhci_mvebu_mbus_init_quirk(pdev); if (ret) goto disable_clk; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_clk; device_wakeup_enable(hcd->self.controller); /* USB 2.0 roothub is stored in the platform_device now. */ hcd = platform_get_drvdata(pdev); xhci = hcd_to_xhci(hcd); xhci->clk = clk; xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto dealloc_usb2_hcd; } if ((node && of_property_read_bool(node, "usb3-lpm-capable")) || (pdata && pdata->usb3_lpm_capable)) xhci->quirks |= XHCI_LPM_SUPPORT; /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; #ifdef CONFIG_USB_XHCI_MTK mtk_xhci_vbus_on(pdev); #endif return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); put_hcd: usb_put_hcd(hcd); return ret; }
static int xhci_mtk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct xhci_hcd_mtk *mtk; const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct phy *phy; int phy_num; int ret = -ENODEV; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_mtk_hc_driver; mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL); if (!mtk) return -ENOMEM; mtk->dev = dev; mtk->vbus = devm_regulator_get(dev, "vbus"); if (IS_ERR(mtk->vbus)) { dev_err(dev, "fail to get vbus\n"); return PTR_ERR(mtk->vbus); } mtk->vusb33 = devm_regulator_get(dev, "vusb33"); if (IS_ERR(mtk->vusb33)) { dev_err(dev, "fail to get vusb33\n"); return PTR_ERR(mtk->vusb33); } mtk->sys_clk = devm_clk_get(dev, "sys_ck"); if (IS_ERR(mtk->sys_clk)) { dev_err(dev, "fail to get sys_ck\n"); return PTR_ERR(mtk->sys_clk); } /* * reference clock is usually a "fixed-clock", make it optional * for backward compatibility and ignore the error if it does * not exist. */ mtk->ref_clk = devm_clk_get(dev, "ref_ck"); if (IS_ERR(mtk->ref_clk)) { if (PTR_ERR(mtk->ref_clk) == -EPROBE_DEFER) return -EPROBE_DEFER; mtk->ref_clk = NULL; } mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); ret = usb_wakeup_of_property_parse(mtk, node); if (ret) return ret; mtk->num_phys = of_count_phandle_with_args(node, "phys", "#phy-cells"); if (mtk->num_phys > 0) { mtk->phys = devm_kcalloc(dev, mtk->num_phys, sizeof(*mtk->phys), GFP_KERNEL); if (!mtk->phys) return -ENOMEM; } else { mtk->num_phys = 0; } pm_runtime_enable(dev); pm_runtime_get_sync(dev); device_enable_async_suspend(dev); ret = xhci_mtk_ldos_enable(mtk); if (ret) goto disable_pm; ret = xhci_mtk_clks_enable(mtk); if (ret) goto disable_ldos; irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; goto disable_clk; } /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); if (ret) goto disable_clk; if (!dev->dma_mask) dev->dma_mask = &dev->coherent_dma_mask; else dma_set_mask(dev, DMA_BIT_MASK(32)); hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { ret = -ENOMEM; goto disable_clk; } /* * USB 2.0 roothub is stored in the platform_device. * Swap it with mtk HCD. */ mtk->hcd = platform_get_drvdata(pdev); platform_set_drvdata(pdev, mtk); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac"); hcd->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_usb2_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc"); if (res) { /* ippc register is optional */ mtk->ippc_regs = devm_ioremap_resource(dev, res); if (IS_ERR(mtk->ippc_regs)) { ret = PTR_ERR(mtk->ippc_regs); goto put_usb2_hcd; } mtk->has_ippc = true; } else { mtk->has_ippc = false; } for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) { phy = devm_of_phy_get_by_index(dev, node, phy_num); if (IS_ERR(phy)) { ret = PTR_ERR(phy); goto put_usb2_hcd; } mtk->phys[phy_num] = phy; } ret = xhci_mtk_phy_init(mtk); if (ret) goto put_usb2_hcd; ret = xhci_mtk_phy_power_on(mtk); if (ret) goto exit_phys; device_init_wakeup(dev, true); xhci = hcd_to_xhci(hcd); xhci->main_hcd = hcd; xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto power_off_phys; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); put_usb3_hcd: xhci_mtk_sch_exit(mtk); usb_put_hcd(xhci->shared_hcd); power_off_phys: xhci_mtk_phy_power_off(mtk); device_init_wakeup(dev, false); exit_phys: xhci_mtk_phy_exit(mtk); put_usb2_hcd: usb_put_hcd(hcd); disable_clk: xhci_mtk_clks_disable(mtk); disable_ldos: xhci_mtk_ldos_disable(mtk); disable_pm: pm_runtime_put_sync(dev); pm_runtime_disable(dev); return ret; }
static int xhci_histb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct xhci_hcd_histb *histb; const struct hc_driver *driver; struct usb_hcd *hcd; struct xhci_hcd *xhci; struct resource *res; int irq; int ret = -ENODEV; if (usb_disabled()) return -ENODEV; driver = &xhci_histb_hc_driver; histb = devm_kzalloc(dev, sizeof(*histb), GFP_KERNEL); if (!histb) return -ENOMEM; histb->dev = dev; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); histb->ctrl = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(histb->ctrl)) return PTR_ERR(histb->ctrl); ret = xhci_histb_clks_get(histb); if (ret) return ret; histb->soft_reset = devm_reset_control_get(dev, "soft"); if (IS_ERR(histb->soft_reset)) { dev_err(dev, "failed to get soft reset\n"); return PTR_ERR(histb->soft_reset); } pm_runtime_enable(dev); pm_runtime_get_sync(dev); device_enable_async_suspend(dev); /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) return ret; hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { ret = -ENOMEM; goto disable_pm; } hcd->regs = histb->ctrl; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); histb->hcd = hcd; dev_set_drvdata(hcd->self.controller, histb); ret = xhci_histb_host_enable(histb); if (ret) goto put_hcd; xhci = hcd_to_xhci(hcd); device_wakeup_enable(hcd->self.controller); xhci->main_hcd = hcd; xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto disable_host; } if (device_property_read_bool(dev, "usb2-lpm-disable")) xhci->quirks |= XHCI_HW_LPM_DISABLE; if (device_property_read_bool(dev, "usb3-lpm-capable")) xhci->quirks |= XHCI_LPM_SUPPORT; /* imod_interval is the interrupt moderation value in nanoseconds. */ xhci->imod_interval = 40000; device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; device_enable_async_suspend(dev); pm_runtime_put_noidle(dev); /* * Prevent runtime pm from being on as default, users should enable * runtime pm using power/control in sysfs. */ pm_runtime_forbid(dev); return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); disable_host: xhci_histb_host_disable(histb); put_hcd: usb_put_hcd(hcd); disable_pm: pm_runtime_put_sync(dev); pm_runtime_disable(dev); return ret; }