static int dwc3_core_init_for_resume(struct dwc3 *dwc) { int ret; ret = reset_control_deassert(dwc->reset); if (ret) return ret; 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; ret = dwc3_core_init(dwc); if (ret) goto disable_clks; return 0; disable_clks: 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); return ret; }
static void dwc3_core_exit(struct dwc3 *dwc) { usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); clk_bulk_disable(dwc->num_clks, dwc->clks); clk_bulk_unprepare(dwc->num_clks, dwc->clks); reset_control_assert(dwc->reset); }
static int rockchip_vpu_remove(struct platform_device *pdev) { struct rockchip_vpu_dev *vpu = platform_get_drvdata(pdev); v4l2_info(&vpu->v4l2_dev, "Removing %s\n", pdev->name); media_device_unregister(&vpu->mdev); v4l2_m2m_unregister_media_controller(vpu->m2m_dev); v4l2_m2m_release(vpu->m2m_dev); media_device_cleanup(&vpu->mdev); if (vpu->vfd_enc) { video_unregister_device(vpu->vfd_enc); video_device_release(vpu->vfd_enc); } v4l2_device_unregister(&vpu->v4l2_dev); clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); pm_runtime_disable(vpu->dev); return 0; }
/** * clk_bulk_prepare - prepare a set of clocks * @num_clks: the number of clk_bulk_data * @clks: the clk_bulk_data table being prepared * * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable. * Returns 0 on success, VMM_EERROR otherwise. */ int clk_bulk_prepare(int num_clks, const struct clk_bulk_data *clks) { int ret; int i; for (i = 0; i < num_clks; i++) { ret = clk_prepare(clks[i].clk); if (ret) { vmm_lerror(__func__, "Failed to prepare clk '%s': %d\n", clks[i].id, ret); goto err; } } return 0; err: clk_bulk_unprepare(i, clks); return ret; }
/** * clk_bulk_prepare - prepare a set of clocks * @num_clks: the number of clk_bulk_data * @clks: the clk_bulk_data table being prepared * * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable. * Returns 0 on success, -EERROR otherwise. */ int __must_check clk_bulk_prepare(int num_clks, const struct clk_bulk_data *clks) { int ret; int i; for (i = 0; i < num_clks; i++) { ret = clk_prepare(clks[i].clk); if (ret) { pr_err("Failed to prepare clk '%s': %d\n", clks[i].id, ret); goto err; } } return 0; err: clk_bulk_unprepare(i, clks); return ret; }
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 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; }
static int rockchip_vpu_probe(struct platform_device *pdev) { const struct of_device_id *match; struct rockchip_vpu_dev *vpu; struct resource *res; int i, ret; vpu = devm_kzalloc(&pdev->dev, sizeof(*vpu), GFP_KERNEL); if (!vpu) return -ENOMEM; vpu->dev = &pdev->dev; vpu->pdev = pdev; mutex_init(&vpu->vpu_mutex); spin_lock_init(&vpu->irqlock); match = of_match_node(of_rockchip_vpu_match, pdev->dev.of_node); vpu->variant = match->data; INIT_DELAYED_WORK(&vpu->watchdog_work, rockchip_vpu_watchdog); for (i = 0; i < vpu->variant->num_clocks; i++) vpu->clocks[i].id = vpu->variant->clk_names[i]; ret = devm_clk_bulk_get(&pdev->dev, vpu->variant->num_clocks, vpu->clocks); if (ret) return ret; res = platform_get_resource(vpu->pdev, IORESOURCE_MEM, 0); vpu->base = devm_ioremap_resource(vpu->dev, res); if (IS_ERR(vpu->base)) return PTR_ERR(vpu->base); vpu->enc_base = vpu->base + vpu->variant->enc_offset; ret = dma_set_coherent_mask(vpu->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(vpu->dev, "Could not set DMA coherent mask.\n"); return ret; } if (vpu->variant->vepu_irq) { int irq; irq = platform_get_irq_byname(vpu->pdev, "vepu"); if (irq <= 0) { dev_err(vpu->dev, "Could not get vepu IRQ.\n"); return -ENXIO; } ret = devm_request_irq(vpu->dev, irq, vpu->variant->vepu_irq, 0, dev_name(vpu->dev), vpu); if (ret) { dev_err(vpu->dev, "Could not request vepu IRQ.\n"); return ret; } } ret = vpu->variant->init(vpu); if (ret) { dev_err(&pdev->dev, "Failed to init VPU hardware\n"); return ret; } pm_runtime_set_autosuspend_delay(vpu->dev, 100); pm_runtime_use_autosuspend(vpu->dev); pm_runtime_enable(vpu->dev); ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks); if (ret) { dev_err(&pdev->dev, "Failed to prepare clocks\n"); return ret; } ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev); if (ret) { dev_err(&pdev->dev, "Failed to register v4l2 device\n"); goto err_clk_unprepare; } platform_set_drvdata(pdev, vpu); vpu->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops); if (IS_ERR(vpu->m2m_dev)) { v4l2_err(&vpu->v4l2_dev, "Failed to init mem2mem device\n"); ret = PTR_ERR(vpu->m2m_dev); goto err_v4l2_unreg; } vpu->mdev.dev = vpu->dev; strlcpy(vpu->mdev.model, DRIVER_NAME, sizeof(vpu->mdev.model)); media_device_init(&vpu->mdev); vpu->v4l2_dev.mdev = &vpu->mdev; ret = rockchip_vpu_video_device_register(vpu); if (ret) { dev_err(&pdev->dev, "Failed to register encoder\n"); goto err_m2m_rel; } ret = media_device_register(&vpu->mdev); if (ret) { v4l2_err(&vpu->v4l2_dev, "Failed to register mem2mem media device\n"); goto err_video_dev_unreg; } return 0; err_video_dev_unreg: if (vpu->vfd_enc) { video_unregister_device(vpu->vfd_enc); video_device_release(vpu->vfd_enc); } err_m2m_rel: v4l2_m2m_release(vpu->m2m_dev); err_v4l2_unreg: v4l2_device_unregister(&vpu->v4l2_dev); err_clk_unprepare: clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); pm_runtime_disable(vpu->dev); return ret; }