* @clk: struct clk * of DPLL to set
* @rate: rounded target rate
*
- * Program the DPLL with the rounded target rate. Returns -EINVAL upon
- * error, or 0 upon success.
+ * Set the DPLL CLKOUT to the target rate. If the DPLL can enter
+ * low-power bypass, and the target rate is the bypass source clock
+ * rate, then configure the DPLL for bypass. Otherwise, round the
+ * target rate if it hasn't been done already, then program and lock
+ * the DPLL. Returns -EINVAL upon error, or 0 upon success.
*/
static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
{
u16 freqsel;
struct dpll_data *dd;
+ int ret;
if (!clk || !rate)
return -EINVAL;
if (rate == omap2_get_dpll_rate(clk))
return 0;
- if (dd->last_rounded_rate != rate)
- omap2_dpll_round_rate(clk, rate);
+ if (dd->bypass_clk->rate == rate &&
+ (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
- if (dd->last_rounded_rate == 0)
- return -EINVAL;
+ pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
+
+ ret = _omap3_noncore_dpll_bypass(clk);
+
+ } else {
+
+ if (dd->last_rounded_rate != rate)
+ omap2_dpll_round_rate(clk, rate);
- freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
- if (!freqsel)
- WARN_ON(1);
+ if (dd->last_rounded_rate == 0)
+ return -EINVAL;
- omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n,
- freqsel);
+ freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
+ if (!freqsel)
+ WARN_ON(1);
+
+ pr_debug("clock: %s: set rate: locking rate to %lu.\n",
+ clk->name, rate);
+
+ ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
+ dd->last_rounded_n, freqsel);
+
+ }
omap3_dpll_recalc(clk);