return -EINVAL;
spin_lock_irqsave(&clockfw_lock, flags);
- if (arch_clock->clk_enable)
+ if (arch_clock->clk_enable) {
ret = arch_clock->clk_enable(clk);
+ if (ret == 0 && clk->flags & RECALC_ON_ENABLE) {
+ if (clk->recalc)
+ (*clk->recalc)(clk, clk->parent->rate,
+ CURRENT_RATE);
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk, CURRENT_RATE);
+ }
+ }
+
spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
goto out;
}
- if (arch_clock->clk_disable)
+ if (arch_clock->clk_disable) {
arch_clock->clk_disable(clk);
+ if (clk->flags & RECALC_ON_ENABLE) {
+ if (clk->recalc)
+ (*clk->recalc)(clk, clk->parent->rate,
+ CURRENT_RATE);
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk, CURRENT_RATE);
+ }
+ }
out:
spin_unlock_irqrestore(&clockfw_lock, flags);
ret = arch_clock->clk_set_rate(clk, rate);
if (ret == 0) {
if (clk->recalc)
- (*clk->recalc)(clk);
+ (*clk->recalc)(clk, clk->parent->rate,
+ CURRENT_RATE);
if (clk->flags & RATE_PROPAGATES)
- propagate_rate(clk);
+ propagate_rate(clk, CURRENT_RATE);
}
}
ret = arch_clock->clk_set_parent(clk, parent);
if (ret == 0) {
if (clk->recalc)
- (*clk->recalc)(clk);
+ (*clk->recalc)(clk, clk->parent->rate,
+ CURRENT_RATE);
if (clk->flags & RATE_PROPAGATES)
- propagate_rate(clk);
+ propagate_rate(clk, CURRENT_RATE);
}
}
__setup("mpurate=", omap_clk_setup);
/* Used for clocks that always have same value as the parent clock */
-void followparent_recalc(struct clk *clk)
+void followparent_recalc(struct clk *clk, unsigned long new_parent_rate,
+ u8 rate_storage)
{
- if (clk == NULL || IS_ERR(clk))
- return;
-
- clk->rate = clk->parent->rate;
+ if (rate_storage == CURRENT_RATE)
+ clk->rate = new_parent_rate;
+ else if (rate_storage == TEMP_RATE)
+ clk->temp_rate = new_parent_rate;
}
/* Propagate rate to children */
-void propagate_rate(struct clk * tclk)
+void propagate_rate(struct clk *tclk, u8 rate_storage)
{
struct clk *clkp;
+ unsigned long parent_rate = 0;
if (tclk == NULL || IS_ERR(tclk))
return;
list_for_each_entry(clkp, &clocks, node) {
if (likely(clkp->parent != tclk))
continue;
+
+ if (rate_storage == CURRENT_RATE)
+ parent_rate = tclk->rate;
+ else if (rate_storage == TEMP_RATE)
+ parent_rate = tclk->temp_rate;
+
if (clkp->recalc)
- clkp->recalc(clkp);
+ clkp->recalc(clkp, parent_rate, rate_storage);
if (clkp->flags & RATE_PROPAGATES)
- propagate_rate(clkp);
+ propagate_rate(clkp, rate_storage);
}
}
list_for_each_entry(clkp, &clocks, node) {
if (unlikely(!clkp->parent)) {
if (clkp->recalc)
- clkp->recalc(clkp);
+ clkp->recalc(clkp, 0, CURRENT_RATE);
if (clkp->flags & RATE_PROPAGATES)
- propagate_rate(clkp);
+ propagate_rate(clkp, CURRENT_RATE);
}
}
}