static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct dwc3 *dwc; int ret; void __iomem *regs; dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); if (!dwc) return -ENOMEM; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; res->start += DWC3_GLOBALS_REGS_START; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) { ret = PTR_ERR(regs); goto err0; } dwc->regs = regs; dwc->regs_size = resource_size(res); dwc3_get_properties(dwc); platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); ret = dwc3_core_get_phy(dwc); if (ret) goto err0; spin_lock_init(&dwc->lock); pm_runtime_set_active(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) goto err1; pm_runtime_forbid(dev); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err2; } ret = dwc3_get_dr_mode(dwc); if (ret) goto err3; ret = dwc3_alloc_scratch_buffers(dwc); if (ret) goto err3; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err4; } dwc3_check_params(dwc); ret = dwc3_core_init_mode(dwc); if (ret) goto err5; dwc3_debugfs_init(dwc); pm_runtime_put(dev); return 0; err5: dwc3_event_buffers_cleanup(dwc); err4: dwc3_free_scratch_buffers(dwc); err3: dwc3_free_event_buffers(dwc); dwc3_ulpi_exit(dwc); err2: pm_runtime_allow(&pdev->dev); err1: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); err0: /* * restore res->start back to its original value so that, in case the * probe is deferred, we don't end up getting error in request the * memory region the next time probe is called. */ res->start -= DWC3_GLOBALS_REGS_START; return ret; }
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res, dwc_res; struct dwc3 *dwc; int ret; u32 mdwidth; void __iomem *regs; dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); if (!dwc) return -ENOMEM; dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks), GFP_KERNEL); if (!dwc->clks) return -ENOMEM; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ dwc_res = *res; dwc_res.start += DWC3_GLOBALS_REGS_START; regs = devm_ioremap_resource(dev, &dwc_res); if (IS_ERR(regs)) return PTR_ERR(regs); dwc->regs = regs; dwc->regs_size = resource_size(&dwc_res); dwc3_get_properties(dwc); dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); if (IS_ERR(dwc->reset)) return PTR_ERR(dwc->reset); if (dev->of_node) { dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); if (ret == -EPROBE_DEFER) return ret; /* * Clocks are optional, but new DT platforms should support all * clocks as required by the DT-binding. */ if (ret) dwc->num_clks = 0; } ret = reset_control_deassert(dwc->reset); if (ret) goto put_clks; ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); if (ret) goto assert_reset; ret = clk_bulk_enable(dwc->num_clks, dwc->clks); if (ret) goto unprepare_clks; platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); spin_lock_init(&dwc->lock); /* Set dma coherent mask to DMA BUS data width */ mdwidth = DWC3_GHWPARAMS0_MDWIDTH(dwc->hwparams.hwparams0); dev_dbg(dev, "Enabling %d-bit DMA addresses.\n", mdwidth); dma_set_coherent_mask(dev, DMA_BIT_MASK(mdwidth)); pm_runtime_set_active(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) goto err1; pm_runtime_forbid(dev); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err2; } ret = dwc3_get_dr_mode(dwc); if (ret) goto err3; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err4; } dwc3_check_params(dwc); ret = dwc3_core_init_mode(dwc); if (ret) goto err5; dwc3_debugfs_init(dwc); pm_runtime_put(dev); return 0; err5: dwc3_event_buffers_cleanup(dwc); err4: dwc3_free_scratch_buffers(dwc); err3: dwc3_free_event_buffers(dwc); err2: pm_runtime_allow(&pdev->dev); err1: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_bulk_disable(dwc->num_clks, dwc->clks); unprepare_clks: clk_bulk_unprepare(dwc->num_clks, dwc->clks); assert_reset: reset_control_assert(dwc->reset); put_clks: clk_bulk_put(dwc->num_clks, dwc->clks); return ret; }