static int __init migor_init(void) { int ret; ret = clk_register(&siumckb_clk); if (ret < 0) return ret; /* Port number used on this machine: port B */ migor_snd_device = platform_device_alloc("soc-audio", 1); if (!migor_snd_device) { ret = -ENOMEM; goto epdevalloc; } platform_set_drvdata(migor_snd_device, &snd_soc_migor); ret = platform_device_add(migor_snd_device); if (ret) goto epdevadd; return 0; epdevadd: platform_device_put(migor_snd_device); epdevalloc: clk_unregister(&siumckb_clk); return ret; }
static void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); const struct acpi_device_id *id; id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); if (id && id->driver_data) clk_unregister(dev->clk); }
void clk_unregister_fixed_factor(struct clk *clk) { struct clk_hw *hw; hw = __clk_get_hw(clk); if (!hw) return; clk_unregister(clk); kfree(to_clk_fixed_factor(hw)); }
static int fsl_dcu_drm_remove(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev); drm_dev_unregister(fsl_dev->drm); drm_dev_unref(fsl_dev->drm); clk_disable_unprepare(fsl_dev->clk); clk_unregister(fsl_dev->pix_clk); return 0; }
static int clk_wzrd_remove(struct platform_device *pdev) { int i; struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev); of_clk_del_provider(pdev->dev.of_node); for (i = 0; i < WZRD_NUM_OUTPUTS; i++) clk_unregister(clk_wzrd->clkout[i]); for (i = 0; i < wzrd_clk_int_max; i++) clk_unregister(clk_wzrd->clks_internal[i]); if (clk_wzrd->speed_grade) { clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb); clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb); } clk_disable_unprepare(clk_wzrd->axi_clk); return 0; }
static __exit void realview_clk_exit(void) { u32_t i; for(i=0; i< ARRAY_SIZE(realview_clocks); i++) { if(!clk_unregister(&realview_clocks[i])) { LOG_E("failed to unregister clock '%s'", realview_clocks[i].name); } } }
static void __init of_dra7_atl_clock_setup(struct device_node *node) { struct dra7_atl_desc *clk_hw = NULL; struct clk_init_data init = { NULL }; const char **parent_names = NULL; struct clk *clk; int ret; clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); if (!clk_hw) { pr_err("%s: could not allocate dra7_atl_desc\n", __func__); return; } clk_hw->hw.init = &init; clk_hw->divider = 1; init.name = node->name; init.ops = &atl_clk_ops; init.flags = CLK_IGNORE_UNUSED; init.num_parents = of_clk_get_parent_count(node); if (init.num_parents != 1) { pr_err("%s: atl clock %s must have 1 parent\n", __func__, node->name); goto cleanup; } parent_names = kzalloc(sizeof(char *), GFP_KERNEL); if (!parent_names) goto cleanup; parent_names[0] = of_clk_get_parent_name(node, 0); init.parent_names = parent_names; clk = ti_clk_register(NULL, &clk_hw->hw, node->name); if (!IS_ERR(clk)) { ret = ti_clk_add_alias(NULL, clk, node->name); if (ret) { clk_unregister(clk); goto cleanup; } of_clk_add_provider(node, of_clk_src_simple_get, clk); kfree(parent_names); return; } cleanup: kfree(parent_names); kfree(clk_hw); }
void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev, struct clk **clks, u32 num_clks) { of_clk_del_provider(pdev->dev.of_node); if (!num_clks || !clks) return; do { clk_unregister(clks[--num_clks]); clks[num_clks] = NULL; } while (num_clks); }
static int exynos_audss_clk_remove(struct platform_device *pdev) { int i; of_clk_del_provider(pdev->dev.of_node); for (i = 0; i < clk_data.clk_num; i++) { if (!IS_ERR(clk_table[i])) clk_unregister(clk_table[i]); } return 0; }
void clk_unregister_gate(struct clk *clk) { struct clk_gate *gate; struct clk_hw *hw; hw = __clk_get_hw(clk); if (!hw) return; gate = to_clk_gate(hw); clk_unregister(clk); kfree(gate); }
void clk_unregister_composite(struct clk *clk) { struct clk_composite *composite; struct clk_hw *hw; hw = __clk_get_hw(clk); if (!hw) return; composite = to_clk_composite(hw); clk_unregister(clk); kfree(composite); }
static void kona_clk_teardown(struct clk *clk) { struct clk_hw *hw; struct kona_clk *bcm_clk; if (!clk) return; hw = __clk_get_hw(clk); if (!hw) { pr_err("%s: clk %p has null hw pointer\n", __func__, clk); return; } clk_unregister(clk); bcm_clk = to_kona_clk(hw); bcm_clk_teardown(bcm_clk); }
bool_t clk_fixed_factor_unregister(struct clk_fixed_factor_t * fclk) { struct clk_t * clk; if(!fclk || !fclk->name) return FALSE; clk = clk_search(fclk->name); if(!clk) return FALSE; if(clk_unregister(clk)) { free(clk); return TRUE; } return FALSE; }
bool_t clk_pll_unregister(struct clk_pll_t * pclk) { struct clk_t * clk; if(!pclk || !pclk->name) return FALSE; clk = clk_search(pclk->name); if(!clk) return FALSE; if(clk_unregister(clk)) { free(clk); return TRUE; } return FALSE; }
bool_t clk_mux_unregister(struct clk_mux_t * mclk) { struct clk_t * clk; if(!mclk || !mclk->name) return FALSE; clk = clk_search(mclk->name); if(!clk) return FALSE; if(clk_unregister(clk)) { free(clk); return TRUE; } return FALSE; }
bool_t clk_gate_unregister(struct clk_gate_t * gclk) { struct clk_t * clk; if(!gclk || !gclk->name) return FALSE; clk = clk_search(gclk->name); if(!clk) return FALSE; if(clk_unregister(clk)) { free(clk); return TRUE; } return FALSE; }
static int fsl_dcu_drm_probe(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev; struct drm_device *drm; struct device *dev = &pdev->dev; struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; struct clk *pix_clk_in; char pix_clk_name[32]; const char *pix_clk_in_name; const struct of_device_id *id; int ret; u8 div_ratio_shift = 0; fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL); if (!fsl_dev) return -ENOMEM; id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); if (!id) return -ENODEV; fsl_dev->soc = id->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); return ret; } fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); return fsl_dev->irq; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, &fsl_dcu_regmap_config); if (IS_ERR(fsl_dev->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(fsl_dev->regmap); } fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { dev_err(dev, "failed to get dcu clock\n"); return PTR_ERR(fsl_dev->clk); } ret = clk_prepare_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); return ret; } pix_clk_in = devm_clk_get(dev, "pix"); if (IS_ERR(pix_clk_in)) { /* legancy binding, use dcu clock as pixel clock input */ pix_clk_in = fsl_dev->clk; } if (of_property_read_bool(dev->of_node, "big-endian")) div_ratio_shift = 24; pix_clk_in_name = __clk_get_name(pix_clk_in); snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name); fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name, pix_clk_in_name, 0, base + DCU_DIV_RATIO, div_ratio_shift, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL); if (IS_ERR(fsl_dev->pix_clk)) { dev_err(dev, "failed to register pix clk\n"); ret = PTR_ERR(fsl_dev->pix_clk); goto disable_clk; } fsl_dev->tcon = fsl_tcon_init(dev); drm = drm_dev_alloc(driver, dev); if (IS_ERR(drm)) { ret = PTR_ERR(drm); goto unregister_pix_clk; } fsl_dev->dev = dev; fsl_dev->drm = drm; fsl_dev->np = dev->of_node; drm->dev_private = fsl_dev; dev_set_drvdata(dev, fsl_dev); ret = drm_dev_register(drm, 0); if (ret < 0) goto unref; return 0; unref: drm_dev_unref(drm); unregister_pix_clk: clk_unregister(fsl_dev->pix_clk); disable_clk: clk_disable_unprepare(fsl_dev->clk); return ret; }
static int clk_wzrd_probe(struct platform_device *pdev) { int i, ret; u32 reg; unsigned long rate; const char *clk_name; struct clk_wzrd *clk_wzrd; struct resource *mem; struct device_node *np = pdev->dev.of_node; clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); if (!clk_wzrd) return -ENOMEM; platform_set_drvdata(pdev, clk_wzrd); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); clk_wzrd->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(clk_wzrd->base)) return PTR_ERR(clk_wzrd->base); ret = of_property_read_u32(np, "speed-grade", &clk_wzrd->speed_grade); if (!ret) { if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) { dev_warn(&pdev->dev, "invalid speed grade '%d'\n", clk_wzrd->speed_grade); clk_wzrd->speed_grade = 0; } } clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1"); if (IS_ERR(clk_wzrd->clk_in1)) { if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER)) dev_err(&pdev->dev, "clk_in1 not found\n"); return PTR_ERR(clk_wzrd->clk_in1); } clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); if (IS_ERR(clk_wzrd->axi_clk)) { if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER)) dev_err(&pdev->dev, "s_axi_aclk not found\n"); return PTR_ERR(clk_wzrd->axi_clk); } ret = clk_prepare_enable(clk_wzrd->axi_clk); if (ret) { dev_err(&pdev->dev, "enabling s_axi_aclk failed\n"); return ret; } rate = clk_get_rate(clk_wzrd->axi_clk); if (rate > WZRD_ACLK_MAX_FREQ) { dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n", rate); ret = -EINVAL; goto err_disable_clk; } /* we don't support fractional div/mul yet */ reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_CLKFBOUT_FRAC_EN; reg |= readl(clk_wzrd->base + WZRD_CLK_CFG_REG(2)) & WZRD_CLKOUT0_FRAC_EN; if (reg) dev_warn(&pdev->dev, "fractional div/mul not supported\n"); /* register multiplier */ reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_CLKFBOUT_MULT_MASK) >> WZRD_CLKFBOUT_MULT_SHIFT; clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(&pdev->dev)); if (!clk_name) { ret = -ENOMEM; goto err_disable_clk; } clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor( &pdev->dev, clk_name, __clk_get_name(clk_wzrd->clk_in1), 0, reg, 1); kfree(clk_name); if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) { dev_err(&pdev->dev, "unable to register fixed-factor clock\n"); ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]); goto err_disable_clk; } /* register div */ reg = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT; clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); if (!clk_name) { ret = -ENOMEM; goto err_rm_int_clk; } clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor( &pdev->dev, clk_name, __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), 0, 1, reg); if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) { dev_err(&pdev->dev, "unable to register divider clock\n"); ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]); goto err_rm_int_clk; } /* register div per output */ for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { const char *clkout_name; if (of_property_read_string_index(np, "clock-output-names", i, &clkout_name)) { dev_err(&pdev->dev, "clock output name not specified\n"); ret = -EINVAL; goto err_rm_int_clks; } reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(2) + i * 12); reg &= WZRD_CLKOUT_DIVIDE_MASK; reg >>= WZRD_CLKOUT_DIVIDE_SHIFT; clk_wzrd->clkout[i] = clk_register_fixed_factor(&pdev->dev, clkout_name, clk_name, 0, 1, reg); if (IS_ERR(clk_wzrd->clkout[i])) { int j; for (j = i + 1; j < WZRD_NUM_OUTPUTS; j++) clk_unregister(clk_wzrd->clkout[j]); dev_err(&pdev->dev, "unable to register divider clock\n"); ret = PTR_ERR(clk_wzrd->clkout[i]); goto err_rm_int_clks; } } kfree(clk_name); clk_wzrd->clk_data.clks = clk_wzrd->clkout; clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data); if (clk_wzrd->speed_grade) { clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier; ret = clk_notifier_register(clk_wzrd->clk_in1, &clk_wzrd->nb); if (ret) dev_warn(&pdev->dev, "unable to register clock notifier\n"); ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb); if (ret) dev_warn(&pdev->dev, "unable to register clock notifier\n"); } return 0; err_rm_int_clks: clk_unregister(clk_wzrd->clks_internal[1]); err_rm_int_clk: kfree(clk_name); clk_unregister(clk_wzrd->clks_internal[0]); err_disable_clk: clk_disable_unprepare(clk_wzrd->axi_clk); return ret; }
static void __init sun8i_a23_mbus_setup(struct device_node *node) { int num_parents = of_clk_get_parent_count(node); const char **parents; const char *clk_name = node->name; struct resource res; struct clk_divider *div; struct clk_gate *gate; struct clk_mux *mux; struct clk *clk; void __iomem *reg; int err; parents = kcalloc(num_parents, sizeof(*parents), GFP_KERNEL); if (!parents) return; reg = of_io_request_and_map(node, 0, of_node_full_name(node)); if (IS_ERR(reg)) { pr_err("Could not get registers for sun8i-mbus-clk\n"); goto err_free_parents; } div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) goto err_unmap; mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) goto err_free_div; gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) goto err_free_mux; of_property_read_string(node, "clock-output-names", &clk_name); of_clk_parent_fill(node, parents, num_parents); gate->reg = reg; gate->bit_idx = SUN8I_MBUS_ENABLE; gate->lock = &sun8i_a23_mbus_lock; div->reg = reg; div->shift = SUN8I_MBUS_DIV_SHIFT; div->width = SUN8I_MBUS_DIV_WIDTH; div->lock = &sun8i_a23_mbus_lock; mux->reg = reg; mux->shift = SUN8I_MBUS_MUX_SHIFT; mux->mask = SUN8I_MBUS_MUX_MASK; mux->lock = &sun8i_a23_mbus_lock; clk = clk_register_composite(NULL, clk_name, parents, num_parents, &mux->hw, &clk_mux_ops, &div->hw, &clk_divider_ops, &gate->hw, &clk_gate_ops, 0); if (IS_ERR(clk)) goto err_free_gate; err = of_clk_add_provider(node, of_clk_src_simple_get, clk); if (err) goto err_unregister_clk; kfree(parents); /* parents is deep copied */ /* The MBUS clocks needs to be always enabled */ __clk_get(clk); clk_prepare_enable(clk); return; err_unregister_clk: /* TODO: The composite clock stuff will leak a bit here. */ clk_unregister(clk); err_free_gate: kfree(gate); err_free_mux: kfree(mux); err_free_div: kfree(div); err_unmap: iounmap(reg); of_address_to_resource(node, 0, &res); release_mem_region(res.start, resource_size(&res)); err_free_parents: kfree(parents); }
/* register exynos_audss clocks */ static int exynos_audss_clk_probe(struct platform_device *pdev) { int i, ret = 0; struct resource *res; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; const char *sclk_pcm_p = "sclk_pcm0"; struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in; const struct of_device_id *match; enum exynos_audss_clk_type variant; match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node); if (!match) return -EINVAL; variant = (enum exynos_audss_clk_type)match->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(reg_base)) { dev_err(&pdev->dev, "failed to map audss registers\n"); return PTR_ERR(reg_base); } clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, GFP_KERNEL); if (!clk_table) return -ENOMEM; clk_data.clks = clk_table; if (variant == TYPE_EXYNOS5420) clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; else clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); pll_in = devm_clk_get(&pdev->dev, "pll_in"); if (!IS_ERR(pll_ref)) mout_audss_p[0] = __clk_get_name(pll_ref); if (!IS_ERR(pll_in)) mout_audss_p[1] = __clk_get_name(pll_in); clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); cdclk = devm_clk_get(&pdev->dev, "cdclk"); sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); if (!IS_ERR(cdclk)) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) mout_i2s_p[2] = __clk_get_name(sclk_audio); clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp", "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL, "dout_aud_bus", "dout_srp", 0, reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s", "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, &lock); clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 0, 0, &lock); clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus", "dout_aud_bus", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 2, 0, &lock); clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s", "dout_i2s", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 3, 0, &lock); clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus", "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); if (variant == TYPE_EXYNOS5420) { clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 9, 0, &lock); } for (i = 0; i < clk_data.clk_num; i++) { if (IS_ERR(clk_table[i])) { dev_err(&pdev->dev, "failed to register clock %d\n", i); ret = PTR_ERR(clk_table[i]); goto unregister; } } ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, &clk_data); if (ret) { dev_err(&pdev->dev, "failed to add clock provider\n"); goto unregister; } #ifdef CONFIG_PM_SLEEP register_syscore_ops(&exynos_audss_clk_syscore_ops); #endif dev_info(&pdev->dev, "setup completed\n"); return 0; unregister: for (i = 0; i < clk_data.clk_num; i++) { if (!IS_ERR(clk_table[i])) clk_unregister(clk_table[i]); } return ret; }
void __exit csi_cleanup_module(void) { clk_disable(&csi_mclk); clk_unregister(&csi_mclk); }
static int fsl_dcu_drm_probe(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev; struct drm_device *drm; struct device *dev = &pdev->dev; struct resource *res; void __iomem *base; struct drm_driver *driver = &fsl_dcu_drm_driver; struct clk *pix_clk_in; char pix_clk_name[32]; const char *pix_clk_in_name; const struct of_device_id *id; int ret; fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL); if (!fsl_dev) return -ENOMEM; id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node); if (!id) return -ENODEV; fsl_dev->soc = id->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "could not get memory IO resource\n"); return -ENODEV; } base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); return ret; } fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); return -ENXIO; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, &fsl_dcu_regmap_config); if (IS_ERR(fsl_dev->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(fsl_dev->regmap); } fsl_dev->clk = devm_clk_get(dev, "dcu"); if (IS_ERR(fsl_dev->clk)) { dev_err(dev, "failed to get dcu clock\n"); return PTR_ERR(fsl_dev->clk); } ret = clk_prepare_enable(fsl_dev->clk); if (ret < 0) { dev_err(dev, "failed to enable dcu clk\n"); return ret; } pix_clk_in = devm_clk_get(dev, "pix"); if (IS_ERR(pix_clk_in)) { /* legancy binding, use dcu clock as pixel clock input */ pix_clk_in = fsl_dev->clk; } pix_clk_in_name = __clk_get_name(pix_clk_in); snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name); fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name, pix_clk_in_name, 0, base + DCU_DIV_RATIO, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL); if (IS_ERR(fsl_dev->pix_clk)) { dev_err(dev, "failed to register pix clk\n"); ret = PTR_ERR(fsl_dev->pix_clk); goto disable_clk; } ret = clk_prepare_enable(fsl_dev->pix_clk); if (ret < 0) { dev_err(dev, "failed to enable pix clk\n"); goto unregister_pix_clk; } fsl_dev->tcon = fsl_tcon_init(dev); drm = drm_dev_alloc(driver, dev); if (!drm) { ret = -ENOMEM; goto disable_pix_clk; } fsl_dev->dev = dev; fsl_dev->drm = drm; fsl_dev->np = dev->of_node; drm->dev_private = fsl_dev; dev_set_drvdata(dev, fsl_dev); ret = drm_dev_register(drm, 0); if (ret < 0) goto unref; DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, drm->primary->index); return 0; unref: drm_dev_unref(drm); disable_pix_clk: clk_disable_unprepare(fsl_dev->pix_clk); unregister_pix_clk: clk_unregister(fsl_dev->pix_clk); disable_clk: clk_disable_unprepare(fsl_dev->clk); return ret; }
static void __exit migor_exit(void) { clk_unregister(&siumckb_clk); platform_device_unregister(migor_snd_device); }