int clk_bulk_get(struct vmm_device *dev, int num_clks, struct clk_bulk_data *clks) { int ret; int i; for (i = 0; i < num_clks; i++) clks[i].clk = NULL; for (i = 0; i < num_clks; i++) { clks[i].clk = clk_get(dev, clks[i].id); if (VMM_IS_ERR(clks[i].clk)) { ret = VMM_PTR_ERR(clks[i].clk); vmm_lerror(dev->name, "Failed to get clk '%s': %d\n", clks[i].id, ret); clks[i].clk = NULL; goto err; } } return 0; err: clk_bulk_put(i, clks); return ret; }
int __must_check clk_bulk_get(struct device_d *dev, int num_clks, struct clk_bulk_data *clks) { int ret; int i; for (i = 0; i < num_clks; i++) clks[i].clk = NULL; for (i = 0; i < num_clks; i++) { clks[i].clk = clk_get(dev, clks[i].id); if (IS_ERR(clks[i].clk)) { ret = PTR_ERR(clks[i].clk); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get clk '%s': %d\n", clks[i].id, ret); clks[i].clk = NULL; goto err; } } return 0; err: clk_bulk_put(i, clks); return ret; }
static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, struct clk_bulk_data *clks) { int ret; int i; for (i = 0; i < num_clks; i++) clks[i].clk = NULL; for (i = 0; i < num_clks; i++) { clks[i].clk = of_clk_get(np, i); if (IS_ERR(clks[i].clk)) { ret = PTR_ERR(clks[i].clk); pr_err("%pOF: Failed to get clk index: %d ret: %d\n", np, i, ret); clks[i].clk = NULL; goto err; } } return 0; err: clk_bulk_put(i, clks); return ret; }
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) { if (IS_ERR_OR_NULL(clks)) return; clk_bulk_put(num_clks, clks); kfree(clks); }
static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) { int ret; /* * We're in the error cleanup already, so we only complain, * but won't emit another error on top of the original one. */ ret = pm_genpd_remove(&pd->genpd); if (ret < 0) dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n", pd->genpd.name, ret); clk_bulk_unprepare(pd->num_clks, pd->clks); clk_bulk_put(pd->num_clks, pd->clks); /* protect the zeroing of pm->num_clks */ mutex_lock(&pd->pmu->mutex); pd->num_clks = 0; mutex_unlock(&pd->pmu->mutex); /* devm will free our memory */ }
static int dwc3_remove(struct platform_device *pdev) { struct dwc3 *dwc = platform_get_drvdata(pdev); pm_runtime_get_sync(&pdev->dev); dwc3_debugfs_exit(dwc); dwc3_core_exit_mode(dwc); dwc3_event_buffers_cleanup(dwc); dwc3_core_exit(dwc); dwc3_ulpi_exit(dwc); pm_runtime_put_sync(&pdev->dev); pm_runtime_allow(&pdev->dev); pm_runtime_disable(&pdev->dev); dwc3_free_event_buffers(dwc); dwc3_free_scratch_buffers(dwc); clk_bulk_put(dwc->num_clks, dwc->clks); return 0; }
static void devm_clk_bulk_release(struct device *dev, void *res) { struct clk_bulk_devres *devres = res; clk_bulk_put(devres->num_clks, devres->clks); }
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, struct device_node *node) { const struct rockchip_domain_info *pd_info; struct rockchip_pm_domain *pd; struct device_node *qos_node; int i, j; u32 id; int error; error = of_property_read_u32(node, "reg", &id); if (error) { dev_err(pmu->dev, "%s: failed to retrieve domain id (reg): %d\n", node->name, error); return -EINVAL; } if (id >= pmu->info->num_domains) { dev_err(pmu->dev, "%s: invalid domain id %d\n", node->name, id); return -EINVAL; } pd_info = &pmu->info->domain_info[id]; if (!pd_info) { dev_err(pmu->dev, "%s: undefined domain id %d\n", node->name, id); return -EINVAL; } pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL); if (!pd) return -ENOMEM; pd->info = pd_info; pd->pmu = pmu; pd->num_clks = of_clk_get_parent_count(node); if (pd->num_clks > 0) { pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL); if (!pd->clks) return -ENOMEM; } else { dev_dbg(pmu->dev, "%s: doesn't have clocks: %d\n", node->name, pd->num_clks); pd->num_clks = 0; } for (i = 0; i < pd->num_clks; i++) { pd->clks[i].clk = of_clk_get(node, i); if (IS_ERR(pd->clks[i].clk)) { error = PTR_ERR(pd->clks[i].clk); dev_err(pmu->dev, "%s: failed to get clk at index %d: %d\n", node->name, i, error); return error; } } error = clk_bulk_prepare(pd->num_clks, pd->clks); if (error) goto err_put_clocks; pd->num_qos = of_count_phandle_with_args(node, "pm_qos", NULL); if (pd->num_qos > 0) { pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(*pd->qos_regmap), GFP_KERNEL); if (!pd->qos_regmap) { error = -ENOMEM; goto err_unprepare_clocks; } for (j = 0; j < MAX_QOS_REGS_NUM; j++) { pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, pd->num_qos, sizeof(u32), GFP_KERNEL); if (!pd->qos_save_regs[j]) { error = -ENOMEM; goto err_unprepare_clocks; } } for (j = 0; j < pd->num_qos; j++) { qos_node = of_parse_phandle(node, "pm_qos", j); if (!qos_node) { error = -ENODEV; goto err_unprepare_clocks; } pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); if (IS_ERR(pd->qos_regmap[j])) { error = -ENODEV; of_node_put(qos_node); goto err_unprepare_clocks; } of_node_put(qos_node); } } error = rockchip_pd_power(pd, true); if (error) { dev_err(pmu->dev, "failed to power on domain '%s': %d\n", node->name, error); goto err_unprepare_clocks; } pd->genpd.name = node->name; pd->genpd.power_off = rockchip_pd_power_off; pd->genpd.power_on = rockchip_pd_power_on; pd->genpd.attach_dev = rockchip_pd_attach_dev; pd->genpd.detach_dev = rockchip_pd_detach_dev; pd->genpd.flags = GENPD_FLAG_PM_CLK; if (pd_info->active_wakeup) pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; pm_genpd_init(&pd->genpd, NULL, false); pmu->genpd_data.domains[id] = &pd->genpd; return 0; err_unprepare_clocks: clk_bulk_unprepare(pd->num_clks, pd->clks); err_put_clocks: clk_bulk_put(pd->num_clks, pd->clks); return error; }
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; }