Пример #1
0
/**
 * omap36xx_gate_clk_enable_with_hsdiv_restore - enable clocks suffering
 *         from HSDivider PWRDN problem Implements Errata ID: i556.
 * @clk: DPLL output struct clk
 *
 * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
 * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
 * valueafter their respective PWRDN bits are set.  Any dummy write
 * (Any other value different from the Read value) to the
 * corresponding CM_CLKSEL register will refresh the dividers.
 */
static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
{
	struct clk_divider *parent;
	struct clk_hw *parent_hw;
	u32 dummy_v, orig_v;
	int ret;

	/* Clear PWRDN bit of HSDIVIDER */
	ret = omap2_dflt_clk_enable(hw);

	/* Parent is the x2 node, get parent of parent for the m2 div */
	parent_hw = clk_hw_get_parent(clk_hw_get_parent(hw));
	parent = to_clk_divider(parent_hw);

	/* Restore the dividers */
	if (!ret) {
		orig_v = ti_clk_ll_ops->clk_readl(parent->reg);
		dummy_v = orig_v;

		/* Write any other value different from the Read value */
		dummy_v ^= (1 << parent->shift);
		ti_clk_ll_ops->clk_writel(dummy_v, parent->reg);

		/* Write the original divider */
		ti_clk_ll_ops->clk_writel(orig_v, parent->reg);
	}

	return ret;
}
Пример #2
0
static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
		unsigned long parent_rate)
{
	u32 numerator, denominator;
	struct clk_divider *div = to_clk_divider(hw);
	int i = 10;


	if(clk_fracdiv_get_config(rate, parent_rate,
				&numerator, &denominator) == 0) {
		while (i--) {
			writel((numerator - 1) << 16 | denominator, div->reg);
			mdelay(1);
			writel(numerator << 16 | denominator, div->reg);
			mdelay(1);
		}
		clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
	} else {
		clk_err("clk_frac_div name=%s can't get rate=%lu\n",
				hw->clk->name, rate);
		return -EINVAL;
	}

	return 0;
}
Пример #3
0
/**
 * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
 *         from HSDivider PWRDN problem Implements Errata ID: i556.
 * @clk: DPLL output struct clk
 *
 * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
 * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
 * valueafter their respective PWRDN bits are set.  Any dummy write
 * (Any other value different from the Read value) to the
 * corresponding CM_CLKSEL register will refresh the dividers.
 */
int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
{
	struct clk_divider *parent;
	struct clk_hw *parent_hw;
	u32 dummy_v, orig_v;
	struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
	int ret;

	/* Clear PWRDN bit of HSDIVIDER */
	ret = omap2_dflt_clk_enable(clk);

	parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
	parent = to_clk_divider(parent_hw);

	/* Restore the dividers */
	if (!ret) {
		orig_v = omap2_clk_readl(omap_clk, parent->reg);
		dummy_v = orig_v;

		/* Write any other value different from the Read value */
		dummy_v ^= (1 << parent->shift);
		omap2_clk_writel(dummy_v, omap_clk, parent->reg);

		/* Write the original divider */
		omap2_clk_writel(orig_v, omap_clk, parent->reg);
	}

	return ret;
}
Пример #4
0
static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
		unsigned long *prate)
{
	int i = 0;
	struct clk_divider *divider =to_clk_divider(hw);
	int max_div = 1 << divider->width;

	for (i = 1; i <= max_div; i++) {
		if (i > 1 && (i % 2 != 0))
			continue;
		if (rate >= (*prate / i))
			return *prate / i;
	}

	return (*prate / max_div);
}
Пример #5
0
static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
		unsigned long parent_rate)
{
	unsigned long rate;
	u64 rate64;
	struct clk_divider *div = to_clk_divider(hw);
	u32 numerator, denominator, reg_val;

	reg_val = readl(div->reg);
	if (reg_val == 0)
		return parent_rate;

	numerator = reg_val >> 16;
	denominator = reg_val & 0xFFFF;
	rate64 = (u64)parent_rate * numerator;
	do_div(rate64, denominator);
	rate = rate64;
	clk_debug("%s: %s new clock rate is %lu, prate %lu (frac %u/%u)\n",
			__func__, hw->clk->name, rate, parent_rate,
			numerator, denominator);
	return rate;
}