/* * Standard clock functions defined in include/linux/clk.h */ int clk_enable(struct clk *clk) { int ret = 0; unsigned long flags; struct clk *parent; if (!clk) return 0; if (IS_ERR(clk)) return -EINVAL; spin_lock_irqsave(&clk->lock, flags); if (WARN(!clk->warned && !clk->prepare_count, "%s: Don't call enable on unprepared clocks\n", clk->dbg_name)) clk->warned = true; if (clk->count == 0) { parent = clk_get_parent(clk); ret = clk_enable(parent); if (ret) goto err_enable_parent; ret = clk_enable(clk->depends); if (ret) goto err_enable_depends; ret = vote_rate_vdd(clk, clk->rate); if (ret) goto err_vote_vdd; trace_clock_enable(clk->dbg_name, 1, smp_processor_id()); if (clk->ops->enable) ret = clk->ops->enable(clk); if (ret) goto err_enable_clock; } else if (clk->flags & CLKFLAG_HANDOFF_RATE) { /* * The clock was already enabled by handoff code so there is no * need to enable it again here. Clearing the handoff flag will * prevent the lateinit handoff code from disabling the clock if * a client driver still has it enabled. */ clk->flags &= ~CLKFLAG_HANDOFF_RATE; goto out; } clk->count++; out: spin_unlock_irqrestore(&clk->lock, flags); return 0; err_enable_clock: unvote_rate_vdd(clk, clk->rate); err_vote_vdd: clk_disable(clk->depends); err_enable_depends: clk_disable(parent); err_enable_parent: spin_unlock_irqrestore(&clk->lock, flags); return ret; }
/** * omap2_clk_enable - request that the system enable a clock * @clk: struct clk * to enable * * Increments the usecount on struct clk @clk. If there were no users * previously, then recurse up the clock tree, enabling all of the * clock's parents and all of the parent clockdomains, and finally, * enabling @clk's clockdomain, and @clk itself. Intended to be * called with the clockfw_lock spinlock held. Returns 0 upon success * or a negative error code upon failure. */ int omap2_clk_enable(struct clk *clk) { int ret; pr_debug("clock: %s: incrementing usecount\n", clk->name); clk->usecount++; if (clk->usecount > 1) return 0; pr_debug("clock: %s: enabling in hardware\n", clk->name); if (clk->parent) { ret = omap2_clk_enable(clk->parent); if (ret) { WARN(1, "clock: %s: could not enable parent %s: %d\n", clk->name, clk->parent->name, ret); goto oce_err1; } } if (clk->clkdm) { ret = clkdm_clk_enable(clk->clkdm, clk); if (ret) { WARN(1, "clock: %s: could not enable clockdomain %s: " "%d\n", clk->name, clk->clkdm->name, ret); goto oce_err2; } } if (clk->ops && clk->ops->enable) { trace_clock_enable(clk->name, 1, smp_processor_id()); ret = clk->ops->enable(clk); if (ret) { WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); goto oce_err3; } } /* If clockdomain supports hardware control, enable it */ if (clk->clkdm) clkdm_allow_idle(clk->clkdm); return 0; oce_err3: if (clk->clkdm) clkdm_clk_disable(clk->clkdm, clk); oce_err2: if (clk->parent) omap2_clk_disable(clk->parent); oce_err1: clk->usecount--; return ret; }
/** * omap2_clk_enable - request that the system enable a clock * @clk: struct clk * to enable * * Increments the usecount on struct clk @clk. If there were no users * previously, then recurse up the clock tree, enabling all of the * clock's parents and all of the parent clockdomains, and finally, * enabling @clk's clockdomain, and @clk itself. Intended to be * called with the clockfw_lock spinlock held. Returns 0 upon success * or a negative error code upon failure. */ int omap2_clk_enable(struct clk *clk) { int ret; pr_debug("clock: %s: incrementing usecount\n", clk->name); clk->usecount++; if (clk->usecount > 1) return 0; pr_debug("clock: %s: enabling in hardware\n", clk->name); if (clk->parent) { ret = omap2_clk_enable(clk->parent); if (ret) { WARN(1, "clock: %s: could not enable parent %s: %d\n", clk->name, clk->parent->name, ret); goto oce_err1; } } if (clkdm_control && clk->clkdm) { ret = clkdm_clk_enable(clk->clkdm, clk); if (ret) { WARN(1, "clock: %s: could not enable clockdomain %s: " "%d\n", clk->name, clk->clkdm->name, ret); goto oce_err2; } } if (clk->ops && clk->ops->enable) { trace_clock_enable(clk->name, 1, get_cpu()); put_cpu(); ret = clk->ops->enable(clk); if (ret) { WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); goto oce_err3; } } return 0; oce_err3: if (clkdm_control && clk->clkdm) clkdm_clk_disable(clk->clkdm, clk); oce_err2: if (clk->parent) omap2_clk_disable(clk->parent); oce_err1: clk->usecount--; return ret; }