static struct clk *_register_interface(struct device *dev, const char *name,
				       const char *parent_name,
				       void __iomem *reg, u8 bit_idx,
				       const struct clk_hw_omap_ops *ops)
{
	struct clk_init_data init = { NULL };
	struct clk_hw_omap *clk_hw;
	struct clk *clk;

	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
	if (!clk_hw)
		return ERR_PTR(-ENOMEM);

	clk_hw->hw.init = &init;
	clk_hw->ops = ops;
	clk_hw->flags = MEMMAP_ADDRESSING;
	clk_hw->enable_reg = reg;
	clk_hw->enable_bit = bit_idx;

	init.name = name;
	init.ops = &ti_interface_clk_ops;
	init.flags = 0;

	init.num_parents = 1;
	init.parent_names = &parent_name;

	clk = clk_register(NULL, &clk_hw->hw);

	if (IS_ERR(clk))
		kfree(clk_hw);
	else
		omap2_init_clk_hw_omap_clocks(&clk_hw->hw);

	return clk;
}
/**
 * omap_clocks_register - register an array of omap_clk
 * @ocs: pointer to an array of omap_clk to register
 */
void __init omap_clocks_register(struct omap_clk oclks[], int cnt)
{
	struct omap_clk *c;

	for (c = oclks; c < oclks + cnt; c++) {
		clkdev_add(&c->lk);
		if (!__clk_init(NULL, c->lk.clk))
			omap2_init_clk_hw_omap_clocks(c->lk.clk);
	}
}
/**
 * _register_dpll - low level registration of a DPLL clock
 * @hw: hardware clock definition for the clock
 * @node: device node for the clock
 *
 * Finalizes DPLL registration process. In case a failure (clk-ref or
 * clk-bypass is missing), the clock is added to retry list and
 * the initialization is retried on later stage.
 */
static void __init _register_dpll(struct clk_hw *hw,
                                  struct device_node *node)
{
    struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
    struct dpll_data *dd = clk_hw->dpll_data;
    struct clk *clk;

    clk = of_clk_get(node, 0);
    if (IS_ERR(clk)) {
        pr_debug("clk-ref missing for %s, retry later\n",
                 node->name);
        if (!ti_clk_retry_init(node, hw, _register_dpll))
            return;

        goto cleanup;
    }

    dd->clk_ref = __clk_get_hw(clk);

    clk = of_clk_get(node, 1);

    if (IS_ERR(clk)) {
        pr_debug("clk-bypass missing for %s, retry later\n",
                 node->name);
        if (!ti_clk_retry_init(node, hw, _register_dpll))
            return;

        goto cleanup;
    }

    dd->clk_bypass = __clk_get_hw(clk);

    /* register the clock */
    clk = clk_register(NULL, &clk_hw->hw);

    if (!IS_ERR(clk)) {
        omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
        of_clk_add_provider(node, of_clk_src_simple_get, clk);
        kfree(clk_hw->hw.init->parent_names);
        kfree(clk_hw->hw.init);
        return;
    }

cleanup:
    kfree(clk_hw->dpll_data);
    kfree(clk_hw->hw.init->parent_names);
    kfree(clk_hw->hw.init);
    kfree(clk_hw);
}
Exemple #4
0
/**
 * _register_dpll_x2 - Registers a DPLLx2 clock
 * @node: device node for this clock
 * @ops: clk_ops for this clock
 * @hw_ops: clk_hw_ops for this clock
 *
 * Initializes a DPLL x 2 clock from device tree data.
 */
static void _register_dpll_x2(struct device_node *node,
			      const struct clk_ops *ops,
			      const struct clk_hw_omap_ops *hw_ops)
{
	struct clk *clk;
	struct clk_init_data init = { NULL };
	struct clk_hw_omap *clk_hw;
	const char *name = node->name;
	const char *parent_name;

	parent_name = of_clk_get_parent_name(node, 0);
	if (!parent_name) {
		pr_err("%s must have parent\n", node->name);
		return;
	}

	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
	if (!clk_hw)
		return;

	clk_hw->ops = hw_ops;
	clk_hw->hw.init = &init;

	init.name = name;
	init.ops = ops;
	init.parent_names = &parent_name;
	init.num_parents = 1;

	/* register the clock */
	clk = clk_register(NULL, &clk_hw->hw);

	if (IS_ERR(clk)) {
		kfree(clk_hw);
	} else {
		omap2_init_clk_hw_omap_clocks(clk);
		of_clk_add_provider(node, of_clk_src_simple_get, clk);
	}
}
Exemple #5
0
int __init am33xx_clk_init(void)
{
	struct omap_clk *c;
	u32 cpu_clkflg;

	if (soc_is_am33xx()) {
		cpu_mask = RATE_IN_AM33XX;
		cpu_clkflg = CK_AM33XX;
	}

	for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
		if (c->cpu & cpu_clkflg) {
			clkdev_add(&c->lk);
			if (!__clk_init(NULL, c->lk.clk))
				omap2_init_clk_hw_omap_clocks(c->lk.clk);
		}
	}

	omap2_clk_disable_autoidle_all();

	omap2_clk_enable_init_clocks(enable_init_clks,
				     ARRAY_SIZE(enable_init_clks));

	/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
	 *    physically present, in such a case HWMOD enabling of
	 *    clock would be failure with default parent. And timer
	 *    probe thinks clock is already enabled, this leads to
	 *    crash upon accessing timer 3 & 6 registers in probe.
	 *    Fix by setting parent of both these timers to master
	 *    oscillator clock.
	 */

	clk_set_parent(&timer3_fck, &sys_clkin_ck);
	clk_set_parent(&timer6_fck, &sys_clkin_ck);

	return 0;
}