Exemplo n.º 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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 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_hw_omap *parent;
	struct clk_hw *parent_hw;
	u32 dummy_v, orig_v, clksel_shift;
	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_hw_omap(parent_hw);

	/* Restore the dividers */
	if (!ret) {
		clksel_shift = __ffs(parent->clksel_mask);
		orig_v = __raw_readl(parent->clksel_reg);
		dummy_v = orig_v;

		/* Write any other value different from the Read value */
		dummy_v ^= (1 << clksel_shift);
		__raw_writel(dummy_v, parent->clksel_reg);

		/* Write the original divider */
		__raw_writel(orig_v, parent->clksel_reg);
	}

	return ret;
}
Exemplo n.º 4
0
/** omap3_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
 *         from HSDivider problem.
 * @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 get lost after their respective PWRDN bits are set.
 * Any write to the corresponding CM_CLKSEL register will refresh the
 * dividers.  Only x2 clocks are affected, so it is safe to trust the parent
 * clock information to refresh the CM_CLKSEL registers.
 */
int omap3_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk)
{
	u32 orig_v, v, c, clksel_shift, max_div;
	int ret;

	/* enable the clock */
	ret = omap2_dflt_clk_enable(clk);

	/* Restore the dividers */
	if (!ret) {
		v = __raw_readl(clk->parent->clksel_reg);
		orig_v = v;

		clksel_shift = __ffs(clk->parent->clksel_mask);

		max_div = clk->parent->clksel_mask >> clksel_shift;

		/* Isolate the current divider */
		c = v & clk->parent->clksel_mask;
		c >>= clksel_shift;

		/* Prevent excessively high clock rates if divider would wrap */
		c += (c == max_div) ? -1 : 1;

		/* Write the temporarily altered divider back */
		c <<= clksel_shift;
		v &= ~c;
		v |= c;
		__raw_writel(v, clk->parent->clksel_reg);

		/* Write the original divider */
		__raw_writel(orig_v, clk->parent->clksel_reg);
	}
Exemplo n.º 5
0
/**
 * am33xx_dflt_wait_clk_enable() - Enable a am33xx module clock
 * @clk: Pointer to the clock to be enabled
 *
 * This function just wraps omap2_dflt_clk_enable with a check for module idle
 * status. We loop till module goes to funcitonal state as the immediate access
 * to module space will not work otherwise.
 */
int am33xx_dflt_wait_clk_enable(struct clk *clk)
{
	omap2_dflt_clk_enable(clk);

	omap2_cm_wait_idlest(clk->enable_reg, AM33XX_IDLEST_MASK,
			AM33XX_IDLEST_VAL, clk->name);

	return 0;
}
Exemplo n.º 6
0
int am33xx_sgx_clk_enable(struct clk *clk)
{
	omap2_dflt_clk_enable(clk);

	/* De-assert local reset after module enable */
	omap2_prm_clear_mod_reg_bits(AM33XX_GFX_RST_MASK,
			AM33XX_PRM_GFX_MOD,
			AM33XX_RM_GFX_RSTCTRL_OFFSET);

	omap2_cm_wait_idlest(clk->enable_reg, AM33XX_IDLEST_MASK,
			AM33XX_IDLEST_VAL, clk->name);

	return 0;
}
Exemplo n.º 7
0
static void clkout_clk_disable(struct clk_hw *hw)
{
	omap2_dflt_clk_enable(hw);
}
Exemplo n.º 8
0
static int clkout_clk_enable(struct clk_hw *hw)
{
	return omap2_dflt_clk_enable(hw);
}