diff options
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r-- | drivers/clk/ti/clk-33xx.c | 2 | ||||
-rw-r--r-- | drivers/clk/ti/clk-dra7-atl.c | 12 | ||||
-rw-r--r-- | drivers/clk/ti/clkt_dpll.c | 36 | ||||
-rw-r--r-- | drivers/clk/ti/clock.h | 6 | ||||
-rw-r--r-- | drivers/clk/ti/composite.c | 6 | ||||
-rw-r--r-- | drivers/clk/ti/divider.c | 12 | ||||
-rw-r--r-- | drivers/clk/ti/dpll.c | 10 | ||||
-rw-r--r-- | drivers/clk/ti/dpll3xxx.c | 7 | ||||
-rw-r--r-- | drivers/clk/ti/dpll44xx.c | 89 | ||||
-rw-r--r-- | drivers/clk/ti/fapll.c | 48 |
10 files changed, 103 insertions, 125 deletions
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index 85c50ea39e6d..9269e6a0db6a 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c @@ -258,6 +258,8 @@ static const char *enable_init_clks[] = { "dpll_ddr_m2_ck", "dpll_mpu_m2_ck", "l3_gclk", + /* WKUP_DEBUGSS_CLKCTRL - disable fails, AM335x Errata Advisory 1.0.42 */ + "l3-aon-clkctrl:0000:0", /* AM3_L3_L3_MAIN_CLKCTRL, needed during suspend */ "l3-clkctrl:00bc:0", "l4hs_gclk", diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 0eab7f3e2eab..b02f84d49b96 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -120,16 +120,18 @@ static unsigned long atl_clk_recalc_rate(struct clk_hw *hw, return parent_rate / cdesc->divider; } -static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int atl_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { unsigned divider; - divider = (*parent_rate + rate / 2) / rate; + divider = (req->best_parent_rate + req->rate / 2) / req->rate; if (divider > DRA7_ATL_DIVIDER_MASK + 1) divider = DRA7_ATL_DIVIDER_MASK + 1; - return *parent_rate / divider; + req->rate = req->best_parent_rate / divider; + + return 0; } static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -156,7 +158,7 @@ static const struct clk_ops atl_clk_ops = { .disable = atl_clk_disable, .is_enabled = atl_clk_is_enabled, .recalc_rate = atl_clk_recalc_rate, - .round_rate = atl_clk_round_rate, + .determine_rate = atl_clk_determine_rate, .set_rate = atl_clk_set_rate, }; diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index dfaa4d1f0b64..2ecd66968af4 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c @@ -268,20 +268,18 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) /* DPLL rate rounding code */ /** - * omap2_dpll_round_rate - round a target rate for an OMAP DPLL + * omap2_dpll_determine_rate - round a target rate for an OMAP DPLL * @hw: struct clk_hw containing the struct clk * for a DPLL - * @target_rate: desired DPLL clock rate - * @parent_rate: parent's DPLL clock rate + * @req: rate request * * Given a DPLL and a desired target rate, round the target rate to a * possible, programmable rate for this DPLL. Attempts to select the * minimum possible n. Stores the computed (m, n) in the DPLL's * dpll_data structure so set_rate() will not need to call this - * (expensive) function again. Returns ~0 if the target rate cannot - * be rounded, or the rounded rate upon success. + * (expensive) function again. Returns -EINVAL if the target rate + * cannot be rounded, or the rounded rate upon success. */ -long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, - unsigned long *parent_rate) +int omap2_dpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct clk_hw_omap *clk = to_clk_hw_omap(hw); int m, n, r, scaled_max_m; @@ -295,19 +293,19 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, const char *clk_name; if (!clk || !clk->dpll_data) - return ~0; + return -EINVAL; dd = clk->dpll_data; - if (dd->max_rate && target_rate > dd->max_rate) - target_rate = dd->max_rate; + if (dd->max_rate && req->rate > dd->max_rate) + req->rate = dd->max_rate; ref_rate = clk_hw_get_rate(dd->clk_ref); clk_name = clk_hw_get_name(hw); pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", - clk_name, target_rate); + clk_name, req->rate); - scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR); + scaled_rt_rp = req->rate / (ref_rate / DPLL_SCALE_FACTOR); scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; dd->last_rounded_rate = 0; @@ -332,7 +330,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, if (m > scaled_max_m) break; - r = _dpll_test_mult(&m, n, &new_rate, target_rate, + r = _dpll_test_mult(&m, n, &new_rate, req->rate, ref_rate); /* m can't be set low enough for this n - try with a larger n */ @@ -340,7 +338,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, continue; /* skip rates above our target rate */ - delta = target_rate - new_rate; + delta = req->rate - new_rate; if (delta < 0) continue; @@ -359,13 +357,15 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, if (prev_min_delta == LONG_MAX) { pr_debug("clock: %s: cannot round to rate %lu\n", - clk_name, target_rate); - return ~0; + clk_name, req->rate); + return -EINVAL; } dd->last_rounded_m = min_delta_m; dd->last_rounded_n = min_delta_n; - dd->last_rounded_rate = target_rate - prev_min_delta; + dd->last_rounded_rate = req->rate - prev_min_delta; - return dd->last_rounded_rate; + req->rate = dd->last_rounded_rate; + + return 0; } diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index 2de7acea1ea0..d5e24fe4ae3a 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -273,8 +273,7 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, u8 index); int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req); -long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, - unsigned long *parent_rate); +int omap2_dpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req); unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate); @@ -296,9 +295,6 @@ void omap3_clk_lock_dpll5(void); unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, unsigned long parent_rate); -long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, - unsigned long target_rate, - unsigned long *parent_rate); int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, struct clk_rate_request *req); int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw)); diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c index b85382c370f7..8cba259188d4 100644 --- a/drivers/clk/ti/composite.c +++ b/drivers/clk/ti/composite.c @@ -26,8 +26,8 @@ static unsigned long ti_composite_recalc_rate(struct clk_hw *hw, return ti_clk_divider_ops.recalc_rate(hw, parent_rate); } -static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int ti_composite_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { return -EINVAL; } @@ -40,7 +40,7 @@ static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops ti_composite_divider_ops = { .recalc_rate = &ti_composite_recalc_rate, - .round_rate = &ti_composite_round_rate, + .determine_rate = &ti_composite_determine_rate, .set_rate = &ti_composite_set_rate, }; diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index ade99ab6cfa9..6f58a0f2e74a 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -223,13 +223,15 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, return bestdiv; } -static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int ti_clk_divider_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { int div; - div = ti_clk_divider_bestdiv(hw, rate, prate); + div = ti_clk_divider_bestdiv(hw, req->rate, &req->best_parent_rate); - return DIV_ROUND_UP(*prate, div); + req->rate = DIV_ROUND_UP(req->best_parent_rate, div); + + return 0; } static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, @@ -299,7 +301,7 @@ static void clk_divider_restore_context(struct clk_hw *hw) const struct clk_ops ti_clk_divider_ops = { .recalc_rate = ti_clk_divider_recalc_rate, - .round_rate = ti_clk_divider_round_rate, + .determine_rate = ti_clk_divider_determine_rate, .set_rate = ti_clk_divider_set_rate, .save_context = clk_divider_save_context, .restore_context = clk_divider_restore_context, diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 3386bd1903df..971adafd9a8b 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -25,7 +25,6 @@ static const struct clk_ops dpll_m4xen_ck_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, .recalc_rate = &omap4_dpll_regm4xen_recalc, - .round_rate = &omap4_dpll_regm4xen_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, @@ -48,7 +47,6 @@ static const struct clk_ops dpll_ck_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, .recalc_rate = &omap3_dpll_recalc, - .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, @@ -61,7 +59,6 @@ static const struct clk_ops dpll_ck_ops = { static const struct clk_ops dpll_no_gate_ck_ops = { .recalc_rate = &omap3_dpll_recalc, .get_parent = &omap2_init_dpll_parent, - .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, @@ -80,7 +77,7 @@ const struct clk_hw_omap_ops clkhwops_omap3_dpll = {}; static const struct clk_ops omap2_dpll_core_ck_ops = { .get_parent = &omap2_init_dpll_parent, .recalc_rate = &omap2_dpllcore_recalc, - .round_rate = &omap2_dpll_round_rate, + .determine_rate = &omap2_dpll_determine_rate, .set_rate = &omap2_reprogram_dpllcore, }; #else @@ -91,7 +88,7 @@ static const struct clk_ops omap2_dpll_core_ck_ops = {}; static const struct clk_ops omap3_dpll_core_ck_ops = { .get_parent = &omap2_init_dpll_parent, .recalc_rate = &omap3_dpll_recalc, - .round_rate = &omap2_dpll_round_rate, + .determine_rate = &omap2_dpll_determine_rate, }; static const struct clk_ops omap3_dpll_ck_ops = { @@ -103,7 +100,6 @@ static const struct clk_ops omap3_dpll_ck_ops = { .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, .determine_rate = &omap3_noncore_dpll_determine_rate, - .round_rate = &omap2_dpll_round_rate, }; static const struct clk_ops omap3_dpll5_ck_ops = { @@ -115,7 +111,6 @@ static const struct clk_ops omap3_dpll5_ck_ops = { .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, .determine_rate = &omap3_noncore_dpll_determine_rate, - .round_rate = &omap2_dpll_round_rate, }; static const struct clk_ops omap3_dpll_per_ck_ops = { @@ -127,7 +122,6 @@ static const struct clk_ops omap3_dpll_per_ck_ops = { .set_parent = &omap3_noncore_dpll_set_parent, .set_rate_and_parent = &omap3_dpll4_set_rate_and_parent, .determine_rate = &omap3_noncore_dpll_determine_rate, - .round_rate = &omap2_dpll_round_rate, }; #endif diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 00680486b1bd..8c51b988a04f 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -587,6 +587,7 @@ int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, { struct clk_hw_omap *clk = to_clk_hw_omap(hw); struct dpll_data *dd; + int ret; if (!req->rate) return -EINVAL; @@ -599,8 +600,10 @@ int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { req->best_parent_hw = dd->clk_bypass; } else { - req->rate = omap2_dpll_round_rate(hw, req->rate, - &req->best_parent_rate); + ret = omap2_dpll_determine_rate(hw, req); + if (ret != 0) + return ret; + req->best_parent_hw = dd->clk_ref; } diff --git a/drivers/clk/ti/dpll44xx.c b/drivers/clk/ti/dpll44xx.c index 3fc2cab69a3f..08ed57f181b4 100644 --- a/drivers/clk/ti/dpll44xx.c +++ b/drivers/clk/ti/dpll44xx.c @@ -134,68 +134,13 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, } /** - * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit - * @hw: struct hw_clk containing the struct clk * of the DPLL to round a rate for - * @target_rate: the desired rate of the DPLL - * @parent_rate: clock rate of the DPLL parent - * - * Compute the rate that would be programmed into the DPLL hardware - * for @clk if set_rate() were to be provided with the rate - * @target_rate. Takes the REGM4XEN bit into consideration, which is - * needed for the OMAP4 ABE DPLL. Returns the rounded rate (before - * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or - * ~0 if an error occurred in omap2_dpll_round_rate(). - */ -long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, - unsigned long target_rate, - unsigned long *parent_rate) -{ - struct clk_hw_omap *clk = to_clk_hw_omap(hw); - struct dpll_data *dd; - long r; - - if (!clk || !clk->dpll_data) - return -EINVAL; - - dd = clk->dpll_data; - - dd->last_rounded_m4xen = 0; - - /* - * First try to compute the DPLL configuration for - * target rate without using the 4X multiplier. - */ - r = omap2_dpll_round_rate(hw, target_rate, NULL); - if (r != ~0) - goto out; - - /* - * If we did not find a valid DPLL configuration, try again, but - * this time see if using the 4X multiplier can help. Enabling the - * 4X multiplier is equivalent to dividing the target rate by 4. - */ - r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT, - NULL); - if (r == ~0) - return r; - - dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; - dd->last_rounded_m4xen = 1; - -out: - omap4_dpll_lpmode_recalc(dd); - - return dd->last_rounded_rate; -} - -/** * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL * @hw: pointer to the clock to determine rate for * @req: target rate request * * Determines which DPLL mode to use for reaching a desired rate. * Checks whether the DPLL shall be in bypass or locked mode, and if - * locked, calculates the M,N values for the DPLL via round-rate. + * locked, calculates the M,N values for the DPLL. * Returns 0 on success and a negative error value otherwise. */ int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, @@ -215,8 +160,36 @@ int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { req->best_parent_hw = dd->clk_bypass; } else { - req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate, - &req->best_parent_rate); + struct clk_rate_request tmp_req; + long r; + + clk_hw_init_rate_request(hw, &tmp_req, req->rate); + dd->last_rounded_m4xen = 0; + + /* + * First try to compute the DPLL configuration for + * target rate without using the 4X multiplier. + */ + + r = omap2_dpll_determine_rate(hw, &tmp_req); + if (r < 0) { + /* + * If we did not find a valid DPLL configuration, try again, but + * this time see if using the 4X multiplier can help. Enabling the + * 4X multiplier is equivalent to dividing the target rate by 4. + */ + tmp_req.rate /= OMAP4430_REGM4XEN_MULT; + r = omap2_dpll_determine_rate(hw, &tmp_req); + if (r < 0) + return r; + + dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; + dd->last_rounded_m4xen = 1; + } + + omap4_dpll_lpmode_recalc(dd); + + req->rate = dd->last_rounded_rate; req->best_parent_hw = dd->clk_ref; } diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 2db3fc4a443e..4f28138d2d8a 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -214,24 +214,27 @@ static int ti_fapll_set_div_mult(unsigned long rate, return 0; } -static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int ti_fapll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { u32 pre_div_p, mult_n; int error; - if (!rate) + if (!req->rate) return -EINVAL; - error = ti_fapll_set_div_mult(rate, *parent_rate, + error = ti_fapll_set_div_mult(req->rate, req->best_parent_rate, &pre_div_p, &mult_n); - if (error) - return error; + if (error) { + req->rate = error; - rate = *parent_rate / pre_div_p; - rate *= mult_n; + return 0; + } - return rate; + req->rate = req->best_parent_rate / pre_div_p; + req->rate *= mult_n; + + return 0; } static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -268,7 +271,7 @@ static const struct clk_ops ti_fapll_ops = { .is_enabled = ti_fapll_is_enabled, .recalc_rate = ti_fapll_recalc_rate, .get_parent = ti_fapll_get_parent, - .round_rate = ti_fapll_round_rate, + .determine_rate = ti_fapll_determine_rate, .set_rate = ti_fapll_set_rate, }; @@ -399,14 +402,14 @@ static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth, return post_div_m; } -static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int ti_fapll_synth_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct fapll_synth *synth = to_synth(hw); struct fapll_data *fd = synth->fd; unsigned long r; - if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) + if (ti_fapll_clock_is_bypass(fd) || !synth->div || !req->rate) return -EINVAL; /* Only post divider m available with no fractional divider? */ @@ -414,23 +417,26 @@ static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long frac_rate; u32 synth_post_div_m; - frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate); - synth_post_div_m = DIV_ROUND_UP(frac_rate, rate); + frac_rate = ti_fapll_synth_get_frac_rate(hw, + req->best_parent_rate); + synth_post_div_m = DIV_ROUND_UP(frac_rate, req->rate); r = DIV_ROUND_UP(frac_rate, synth_post_div_m); goto out; } - r = *parent_rate * SYNTH_PHASE_K; - if (rate > r) + r = req->best_parent_rate * SYNTH_PHASE_K; + if (req->rate > r) goto out; r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M); - if (rate < r) + if (req->rate < r) goto out; - r = rate; + r = req->rate; out: - return r; + req->rate = r; + + return 0; } static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, @@ -477,7 +483,7 @@ static const struct clk_ops ti_fapll_synt_ops = { .disable = ti_fapll_synth_disable, .is_enabled = ti_fapll_synth_is_enabled, .recalc_rate = ti_fapll_synth_recalc_rate, - .round_rate = ti_fapll_synth_round_rate, + .determine_rate = ti_fapll_synth_determine_rate, .set_rate = ti_fapll_synth_set_rate, }; |