int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) { u32 v, field_val, validrate, new_div = 0; if (!clk->clksel_mask) return -EINVAL; validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); if (validrate != rate) return -EINVAL; field_val = omap2_divisor_to_clksel(clk, new_div); if (field_val == ~0) return -EINVAL; v = __raw_readl(clk->clksel_reg); v &= ~clk->clksel_mask; v |= field_val << __ffs(clk->clksel_mask); __raw_writel(v, clk->clksel_reg); v = __raw_readl(clk->clksel_reg); /* OCP barrier */ clk->rate = clk->parent->rate / new_div; _omap2xxx_clk_commit(clk); return 0; }
int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) { u32 field_val, v, parent_div; if (clk->flags & CONFIG_PARTICIPANT) return -EINVAL; if (!clk->clksel) return -EINVAL; parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val); if (!parent_div) return -EINVAL; /* Set new source value (previous dividers if any in effect) */ v = __raw_readl(clk->clksel_reg); v &= ~clk->clksel_mask; v |= field_val << __ffs(clk->clksel_mask); __raw_writel(v, clk->clksel_reg); v = __raw_readl(clk->clksel_reg); /* OCP barrier */ _omap2xxx_clk_commit(clk); clk_reparent(clk, new_parent); /* CLKSEL clocks follow their parents' rates, divided by a divisor */ clk->rate = new_parent->rate; if (parent_div > 0) clk->rate /= parent_div; pr_debug("clock: set parent of %s to %s (new rate %ld)\n", clk->name, clk->parent->name, clk->rate); return 0; }
int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) { u32 field_val, v, parent_div; if (clk->flags & CONFIG_PARTICIPANT) return -EINVAL; if (!clk->clksel) return -EINVAL; parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val); if (!parent_div) return -EINVAL; v = __raw_readl(clk->clksel_reg); v &= ~clk->clksel_mask; v |= field_val << __ffs(clk->clksel_mask); __raw_writel(v, clk->clksel_reg); v = __raw_readl(clk->clksel_reg); _omap2xxx_clk_commit(clk); clk_reparent(clk, new_parent); clk->rate = new_parent->rate; if (parent_div > 0) clk->rate /= parent_div; pr_debug("clock: set parent of %s to %s (new rate %ld)\n", clk->name, clk->parent->name, clk->rate); return 0; }