diff options
author | Tero Kristo <t-kristo@ti.com> | 2016-02-20 06:24:26 -0500 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2016-02-22 17:16:49 -0500 |
commit | b6f5128459a40410f9afefddc0ad688ea5b22c28 (patch) | |
tree | dfd2a78beabd091b5c49d8aa045497061c1d1855 /drivers/clk/ti | |
parent | 1e59403990acfb67d0e9ddf57fe6acc1c2aff4dc (diff) |
clk: ti: dpll: convert DPLL support code to use clk_hw instead of clk ptrs
Convert DPLL support code to use clk_hw pointers for reference and bypass
clocks. This allows us to use clk_hw_* APIs for accessing any required
parameters for these clocks, avoiding some locking problems at least with
DPLL enable code; this used clk_get_rate which uses mutex but isn't
good under clk_enable / clk_disable.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r-- | drivers/clk/ti/apll.c | 20 | ||||
-rw-r--r-- | drivers/clk/ti/clkt_dpll.c | 6 | ||||
-rw-r--r-- | drivers/clk/ti/dpll.c | 25 | ||||
-rw-r--r-- | drivers/clk/ti/dpll3xxx.c | 17 | ||||
-rw-r--r-- | drivers/clk/ti/dpll44xx.c | 8 |
5 files changed, 50 insertions, 26 deletions
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index b336a8c11e2a..6411e132faa2 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c | |||
@@ -140,11 +140,21 @@ static void __init omap_clk_register_apll(struct clk_hw *hw, | |||
140 | struct dpll_data *ad = clk_hw->dpll_data; | 140 | struct dpll_data *ad = clk_hw->dpll_data; |
141 | struct clk *clk; | 141 | struct clk *clk; |
142 | 142 | ||
143 | ad->clk_ref = of_clk_get(node, 0); | 143 | clk = of_clk_get(node, 0); |
144 | ad->clk_bypass = of_clk_get(node, 1); | 144 | if (IS_ERR(clk)) { |
145 | pr_debug("clk-ref for %s not ready, retry\n", | ||
146 | node->name); | ||
147 | if (!ti_clk_retry_init(node, hw, omap_clk_register_apll)) | ||
148 | return; | ||
149 | |||
150 | goto cleanup; | ||
151 | } | ||
145 | 152 | ||
146 | if (IS_ERR(ad->clk_ref) || IS_ERR(ad->clk_bypass)) { | 153 | ad->clk_ref = __clk_get_hw(clk); |
147 | pr_debug("clk-ref or clk-bypass for %s not ready, retry\n", | 154 | |
155 | clk = of_clk_get(node, 1); | ||
156 | if (IS_ERR(clk)) { | ||
157 | pr_debug("clk-bypass for %s not ready, retry\n", | ||
148 | node->name); | 158 | node->name); |
149 | if (!ti_clk_retry_init(node, hw, omap_clk_register_apll)) | 159 | if (!ti_clk_retry_init(node, hw, omap_clk_register_apll)) |
150 | return; | 160 | return; |
@@ -152,6 +162,8 @@ static void __init omap_clk_register_apll(struct clk_hw *hw, | |||
152 | goto cleanup; | 162 | goto cleanup; |
153 | } | 163 | } |
154 | 164 | ||
165 | ad->clk_bypass = __clk_get_hw(clk); | ||
166 | |||
155 | clk = clk_register(NULL, &clk_hw->hw); | 167 | clk = clk_register(NULL, &clk_hw->hw); |
156 | if (!IS_ERR(clk)) { | 168 | if (!IS_ERR(clk)) { |
157 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 169 | of_clk_add_provider(node, of_clk_src_simple_get, clk); |
diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index b5cc6f66ae5d..032c658a5f5e 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c | |||
@@ -254,7 +254,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) | |||
254 | v >>= __ffs(dd->enable_mask); | 254 | v >>= __ffs(dd->enable_mask); |
255 | 255 | ||
256 | if (_omap2_dpll_is_in_bypass(v)) | 256 | if (_omap2_dpll_is_in_bypass(v)) |
257 | return clk_get_rate(dd->clk_bypass); | 257 | return clk_hw_get_rate(dd->clk_bypass); |
258 | 258 | ||
259 | v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); | 259 | v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); |
260 | dpll_mult = v & dd->mult_mask; | 260 | dpll_mult = v & dd->mult_mask; |
@@ -262,7 +262,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) | |||
262 | dpll_div = v & dd->div1_mask; | 262 | dpll_div = v & dd->div1_mask; |
263 | dpll_div >>= __ffs(dd->div1_mask); | 263 | dpll_div >>= __ffs(dd->div1_mask); |
264 | 264 | ||
265 | dpll_clk = (u64)clk_get_rate(dd->clk_ref) * dpll_mult; | 265 | dpll_clk = (u64)clk_hw_get_rate(dd->clk_ref) * dpll_mult; |
266 | do_div(dpll_clk, dpll_div + 1); | 266 | do_div(dpll_clk, dpll_div + 1); |
267 | 267 | ||
268 | return dpll_clk; | 268 | return dpll_clk; |
@@ -301,7 +301,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, | |||
301 | 301 | ||
302 | dd = clk->dpll_data; | 302 | dd = clk->dpll_data; |
303 | 303 | ||
304 | ref_rate = clk_get_rate(dd->clk_ref); | 304 | ref_rate = clk_hw_get_rate(dd->clk_ref); |
305 | clk_name = clk_hw_get_name(hw); | 305 | clk_name = clk_hw_get_name(hw); |
306 | pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", | 306 | pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", |
307 | clk_name, target_rate); | 307 | clk_name, target_rate); |
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 5519b386edc0..f8306f1c30f1 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c | |||
@@ -147,11 +147,22 @@ static void __init _register_dpll(struct clk_hw *hw, | |||
147 | struct dpll_data *dd = clk_hw->dpll_data; | 147 | struct dpll_data *dd = clk_hw->dpll_data; |
148 | struct clk *clk; | 148 | struct clk *clk; |
149 | 149 | ||
150 | dd->clk_ref = of_clk_get(node, 0); | 150 | clk = of_clk_get(node, 0); |
151 | dd->clk_bypass = of_clk_get(node, 1); | 151 | if (IS_ERR(clk)) { |
152 | pr_debug("clk-ref missing for %s, retry later\n", | ||
153 | node->name); | ||
154 | if (!ti_clk_retry_init(node, hw, _register_dpll)) | ||
155 | return; | ||
152 | 156 | ||
153 | if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) { | 157 | goto cleanup; |
154 | pr_debug("clk-ref or clk-bypass missing for %s, retry later\n", | 158 | } |
159 | |||
160 | dd->clk_ref = __clk_get_hw(clk); | ||
161 | |||
162 | clk = of_clk_get(node, 1); | ||
163 | |||
164 | if (IS_ERR(clk)) { | ||
165 | pr_debug("clk-bypass missing for %s, retry later\n", | ||
155 | node->name); | 166 | node->name); |
156 | if (!ti_clk_retry_init(node, hw, _register_dpll)) | 167 | if (!ti_clk_retry_init(node, hw, _register_dpll)) |
157 | return; | 168 | return; |
@@ -159,6 +170,8 @@ static void __init _register_dpll(struct clk_hw *hw, | |||
159 | goto cleanup; | 170 | goto cleanup; |
160 | } | 171 | } |
161 | 172 | ||
173 | dd->clk_bypass = __clk_get_hw(clk); | ||
174 | |||
162 | /* register the clock */ | 175 | /* register the clock */ |
163 | clk = clk_register(NULL, &clk_hw->hw); | 176 | clk = clk_register(NULL, &clk_hw->hw); |
164 | 177 | ||
@@ -251,8 +264,8 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup) | |||
251 | dd->recal_en_bit = dpll->recal_en_bit; | 264 | dd->recal_en_bit = dpll->recal_en_bit; |
252 | dd->recal_st_bit = dpll->recal_st_bit; | 265 | dd->recal_st_bit = dpll->recal_st_bit; |
253 | 266 | ||
254 | dd->clk_ref = clk_ref; | 267 | dd->clk_ref = __clk_get_hw(clk_ref); |
255 | dd->clk_bypass = clk_bypass; | 268 | dd->clk_bypass = __clk_get_hw(clk_bypass); |
256 | 269 | ||
257 | if (dpll->flags & CLKF_CORE) | 270 | if (dpll->flags & CLKF_CORE) |
258 | ops = &omap3_dpll_core_ck_ops; | 271 | ops = &omap3_dpll_core_ck_ops; |
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index cc739291a3ce..88f2ce81ba55 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c | |||
@@ -98,7 +98,7 @@ static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n) | |||
98 | unsigned long fint; | 98 | unsigned long fint; |
99 | u16 f = 0; | 99 | u16 f = 0; |
100 | 100 | ||
101 | fint = clk_get_rate(clk->dpll_data->clk_ref) / n; | 101 | fint = clk_hw_get_rate(clk->dpll_data->clk_ref) / n; |
102 | 102 | ||
103 | pr_debug("clock: fint is %lu\n", fint); | 103 | pr_debug("clock: fint is %lu\n", fint); |
104 | 104 | ||
@@ -460,12 +460,11 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw) | |||
460 | 460 | ||
461 | parent = clk_hw_get_parent(hw); | 461 | parent = clk_hw_get_parent(hw); |
462 | 462 | ||
463 | if (clk_hw_get_rate(hw) == | 463 | if (clk_hw_get_rate(hw) == clk_hw_get_rate(dd->clk_bypass)) { |
464 | clk_hw_get_rate(__clk_get_hw(dd->clk_bypass))) { | 464 | WARN_ON(parent != dd->clk_bypass); |
465 | WARN_ON(parent != __clk_get_hw(dd->clk_bypass)); | ||
466 | r = _omap3_noncore_dpll_bypass(clk); | 465 | r = _omap3_noncore_dpll_bypass(clk); |
467 | } else { | 466 | } else { |
468 | WARN_ON(parent != __clk_get_hw(dd->clk_ref)); | 467 | WARN_ON(parent != dd->clk_ref); |
469 | r = _omap3_noncore_dpll_lock(clk); | 468 | r = _omap3_noncore_dpll_lock(clk); |
470 | } | 469 | } |
471 | 470 | ||
@@ -513,13 +512,13 @@ int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, | |||
513 | if (!dd) | 512 | if (!dd) |
514 | return -EINVAL; | 513 | return -EINVAL; |
515 | 514 | ||
516 | if (clk_get_rate(dd->clk_bypass) == req->rate && | 515 | if (clk_hw_get_rate(dd->clk_bypass) == req->rate && |
517 | (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { | 516 | (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { |
518 | req->best_parent_hw = __clk_get_hw(dd->clk_bypass); | 517 | req->best_parent_hw = dd->clk_bypass; |
519 | } else { | 518 | } else { |
520 | req->rate = omap2_dpll_round_rate(hw, req->rate, | 519 | req->rate = omap2_dpll_round_rate(hw, req->rate, |
521 | &req->best_parent_rate); | 520 | &req->best_parent_rate); |
522 | req->best_parent_hw = __clk_get_hw(dd->clk_ref); | 521 | req->best_parent_hw = dd->clk_ref; |
523 | } | 522 | } |
524 | 523 | ||
525 | req->best_parent_rate = req->rate; | 524 | req->best_parent_rate = req->rate; |
@@ -577,7 +576,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, | |||
577 | if (!dd) | 576 | if (!dd) |
578 | return -EINVAL; | 577 | return -EINVAL; |
579 | 578 | ||
580 | if (clk_hw_get_parent(hw) != __clk_get_hw(dd->clk_ref)) | 579 | if (clk_hw_get_parent(hw) != dd->clk_ref) |
581 | return -EINVAL; | 580 | return -EINVAL; |
582 | 581 | ||
583 | if (dd->last_rounded_rate == 0) | 582 | if (dd->last_rounded_rate == 0) |
diff --git a/drivers/clk/ti/dpll44xx.c b/drivers/clk/ti/dpll44xx.c index 660d7436ac24..82c05b55a7be 100644 --- a/drivers/clk/ti/dpll44xx.c +++ b/drivers/clk/ti/dpll44xx.c | |||
@@ -94,7 +94,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd) | |||
94 | { | 94 | { |
95 | long fint, fout; | 95 | long fint, fout; |
96 | 96 | ||
97 | fint = clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1); | 97 | fint = clk_hw_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1); |
98 | fout = fint * dd->last_rounded_m; | 98 | fout = fint * dd->last_rounded_m; |
99 | 99 | ||
100 | if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX)) | 100 | if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX)) |
@@ -212,13 +212,13 @@ int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, | |||
212 | if (!dd) | 212 | if (!dd) |
213 | return -EINVAL; | 213 | return -EINVAL; |
214 | 214 | ||
215 | if (clk_get_rate(dd->clk_bypass) == req->rate && | 215 | if (clk_hw_get_rate(dd->clk_bypass) == req->rate && |
216 | (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { | 216 | (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { |
217 | req->best_parent_hw = __clk_get_hw(dd->clk_bypass); | 217 | req->best_parent_hw = dd->clk_bypass; |
218 | } else { | 218 | } else { |
219 | req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate, | 219 | req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate, |
220 | &req->best_parent_rate); | 220 | &req->best_parent_rate); |
221 | req->best_parent_hw = __clk_get_hw(dd->clk_ref); | 221 | req->best_parent_hw = dd->clk_ref; |
222 | } | 222 | } |
223 | 223 | ||
224 | req->best_parent_rate = req->rate; | 224 | req->best_parent_rate = req->rate; |