/** * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode * @clk: pointer to a DPLL struct clk * * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. * The choice of modes depends on the DPLL's programmed rate: if it is * the same as the DPLL's parent clock, it will enter bypass; * otherwise, it will enter lock. This code will wait for the DPLL to * indicate readiness before returning, unless the DPLL takes too long * to enter the target state. Intended to be used as the struct clk's * enable function. If DPLL3 was passed in, or the DPLL does not * support low-power stop, or if the DPLL took too long to enter * bypass or lock, return -EINVAL; otherwise, return 0. */ static int omap3_noncore_dpll_enable(struct clk *clk) { int r; struct dpll_data *dd; if (clk == &dpll3_ck) return -EINVAL; dd = clk->dpll_data; if (!dd) return -EINVAL; /* * Ensure M/N register is confgured before * Enable it, otherwise DPLL will fail to lock */ if (clk->rate == 0) { WARN_ON(dd->default_rate == 0); r = omap3_noncore_dpll_set_rate(clk, dd->default_rate); if (r) return r; } if (clk->rate == dd->clk_bypass->rate) { WARN_ON(clk->parent != dd->clk_bypass); r = _omap3_noncore_dpll_bypass(clk); } else { WARN_ON(clk->parent != dd->clk_ref); r = _omap3_noncore_dpll_lock(clk); } /* FIXME: this is dubious - if clk->rate has changed, what about propagating? */ if (!r) clk->rate = omap2_get_dpll_rate(clk); return r; }
/** * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode * @clk: pointer to a DPLL struct clk * * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. * The choice of modes depends on the DPLL's programmed rate: if it is * the same as the DPLL's parent clock, it will enter bypass; * otherwise, it will enter lock. This code will wait for the DPLL to * indicate readiness before returning, unless the DPLL takes too long * to enter the target state. Intended to be used as the struct clk's * enable function. If DPLL3 was passed in, or the DPLL does not * support low-power stop, or if the DPLL took too long to enter * bypass or lock, return -EINVAL; otherwise, return 0. */ static int omap3_noncore_dpll_enable(struct clk *clk) { int r; struct dpll_data *dd; if (clk == &dpll3_ck) return -EINVAL; dd = clk->dpll_data; if (!dd) return -EINVAL; /* * Ensure M/N register is confgured before * Enable it, otherwise DPLL will fail to lock */ if (clk->rate == 0) { WARN_ON(dd->default_rate == 0); r = omap3_noncore_dpll_set_rate(clk, dd->default_rate); if (r) return r; } if (clk->rate == dd->bypass_clk->rate) r = _omap3_noncore_dpll_bypass(clk); else r = _omap3_noncore_dpll_lock(clk); return r; }
static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) { if (omap_rev() == OMAP3430_REV_ES1_0) { printk(KERN_ERR "clock: DPLL4 cannot change rate due to " "silicon 'Limitation 2.5' on 3430ES1.\n"); return -EINVAL; } return omap3_noncore_dpll_set_rate(clk, rate); }
static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) { /* * According to the 12-5 CDP code from TI, "Limitation 2.5" * on 3430ES1 prevents us from changing DPLL multipliers or dividers * on DPLL4. */ if (omap_rev() == OMAP3430_REV_ES1_0) { printk(KERN_ERR "clock: DPLL4 cannot change rate due to " "silicon 'Limitation 2.5' on 3430ES1.\n"); return -EINVAL; } return omap3_noncore_dpll_set_rate(clk, rate); }
/** * omap3_dpll4_set_rate - set rate for omap3 per-dpll * @hw: clock to change * @rate: target rate for clock * @parent_rate: rate of the parent clock * * Check if the current SoC supports the per-dpll reprogram operation * or not, and then do the rate change if supported. Returns -EINVAL * if not supported, 0 for success, and potential error codes from the * clock rate change. */ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { /* * According to the 12-5 CDP code from TI, "Limitation 2.5" * on 3430ES1 prevents us from changing DPLL multipliers or dividers * on DPLL4. */ if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) { pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n"); return -EINVAL; } return omap3_noncore_dpll_set_rate(hw, rate, parent_rate); }
/** * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock * @hw: pointer to the clock to set rate and parent for * @rate: target rate for the DPLL * @parent_rate: clock rate of the DPLL parent * @index: new parent index for the DPLL, 0 - reference, 1 - bypass * * Sets rate and parent for a DPLL clock. If new parent is the bypass * clock, only selects the parent. Otherwise proceeds with a rate * change, as this will effectively also change the parent as the * DPLL is put into locked mode. Returns 0 with success, negative error * value otherwise. */ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index) { int ret; if (!hw || !rate) return -EINVAL; /* * clk-ref at index[0], in which case we only need to set rate, * the parent will be changed automatically with the lock sequence. * With clk-bypass case we only need to change parent. */ if (index) ret = omap3_noncore_dpll_set_parent(hw, index); else ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate); return ret; }