260
259
/* DPLL rate rounding code */
263
* omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding
264
* @clk: struct clk * of the DPLL
265
* @tolerance: maximum rate error tolerance
267
* Set the maximum DPLL rate error tolerance for the rate rounding
268
* algorithm. The rate tolerance is an attempt to balance DPLL power
269
* saving (the least divider value "n") vs. rate fidelity (the least
270
* difference between the desired DPLL target rate and the rounded
271
* rate out of the algorithm). So, increasing the tolerance is likely
272
* to decrease DPLL power consumption and increase DPLL rate error.
273
* Returns -EINVAL if provided a null clock ptr or a clk that is not a
274
* DPLL; or 0 upon success.
276
int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
278
if (!clk || !clk->dpll_data)
281
clk->dpll_data->rate_tolerance = tolerance;
287
262
* omap2_dpll_round_rate - round a target rate for an OMAP DPLL
288
263
* @clk: struct clk * for a DPLL
289
264
* @target_rate: desired DPLL clock rate
291
* Given a DPLL, a desired target rate, and a rate tolerance, round
292
* the target rate to a possible, programmable rate for this DPLL.
293
* Rate tolerance is assumed to be set by the caller before this
294
* function is called. Attempts to select the minimum possible n
295
* within the tolerance to reduce power consumption. Stores the
296
* computed (m, n) in the DPLL's dpll_data structure so set_rate()
297
* will not need to call this (expensive) function again. Returns ~0
298
* if the target rate cannot be rounded, either because the rate is
299
* too low or because the rate tolerance is set too tightly; or the
300
* rounded rate upon success.
266
* Given a DPLL and a desired target rate, round the target rate to a
267
* possible, programmable rate for this DPLL. Attempts to select the
268
* minimum possible n. Stores the computed (m, n) in the DPLL's
269
* dpll_data structure so set_rate() will not need to call this
270
* (expensive) function again. Returns ~0 if the target rate cannot
271
* be rounded, or the rounded rate upon success.
302
273
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
304
int m, n, r, e, scaled_max_m;
305
unsigned long scaled_rt_rp, new_rate;
306
int min_e = -1, min_e_m = -1, min_e_n = -1;
275
int m, n, r, scaled_max_m;
276
unsigned long scaled_rt_rp;
277
unsigned long new_rate = 0;
307
278
struct dpll_data *dd;
309
280
if (!clk || !clk->dpll_data)
312
283
dd = clk->dpll_data;
314
pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
315
"%ld\n", clk->name, target_rate);
285
pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
286
clk->name, target_rate);
317
288
scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
318
289
scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
347
318
if (r == DPLL_MULT_UNDERFLOW)
350
e = target_rate - new_rate;
351
pr_debug("clock: n = %d: m = %d: rate error is %d "
352
"(new_rate = %ld)\n", n, m, e, new_rate);
355
min_e >= (int)(abs(e) - dd->rate_tolerance)) {
360
pr_debug("clock: found new least error %d\n", min_e);
362
/* We found good settings -- bail out now */
363
if (min_e <= dd->rate_tolerance)
321
pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
322
clk->name, m, n, new_rate);
324
if (target_rate == new_rate) {
325
dd->last_rounded_m = m;
326
dd->last_rounded_n = n;
327
dd->last_rounded_rate = target_rate;
369
pr_debug("clock: error: target rate or tolerance too low\n");
332
if (target_rate != new_rate) {
333
pr_debug("clock: %s: cannot round to rate %ld\n", clk->name,
373
dd->last_rounded_m = min_e_m;
374
dd->last_rounded_n = min_e_n;
375
dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
378
pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
379
min_e, min_e_m, min_e_n);
380
pr_debug("clock: final rate: %ld (target rate: %ld)\n",
381
dd->last_rounded_rate, target_rate);
383
return dd->last_rounded_rate;