diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2015-07-28 14:51:30 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2015-07-28 14:51:30 -0400 |
commit | 19aab273083fa10c2262b8c8e3315bacb054d75d (patch) | |
tree | 65097982915b51acdf8d5576d63153085b779ceb /drivers/clk/clk.c | |
parent | 86665d2897209429a7e4a003764b9fc5034dbfa1 (diff) | |
parent | 57d866e606ddf2a0cd51f7140cfd8df1fdaa48f6 (diff) |
Merge branch 'clk-determine-rate-struct' into clk-next
* clk-determine-rate-struct:
clk: fix some determine_rate implementations
clk: change clk_ops' ->determine_rate() prototype
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 179 |
1 files changed, 99 insertions, 80 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7873151a7ff8..bd6dfbe04cf0 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -436,28 +436,31 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, | |||
436 | return now <= rate && now > best; | 436 | return now <= rate && now > best; |
437 | } | 437 | } |
438 | 438 | ||
439 | static long | 439 | static int |
440 | clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, | 440 | clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req, |
441 | unsigned long min_rate, | ||
442 | unsigned long max_rate, | ||
443 | unsigned long *best_parent_rate, | ||
444 | struct clk_hw **best_parent_p, | ||
445 | unsigned long flags) | 441 | unsigned long flags) |
446 | { | 442 | { |
447 | struct clk_core *core = hw->core, *parent, *best_parent = NULL; | 443 | struct clk_core *core = hw->core, *parent, *best_parent = NULL; |
448 | int i, num_parents; | 444 | int i, num_parents, ret; |
449 | unsigned long parent_rate, best = 0; | 445 | unsigned long best = 0; |
446 | struct clk_rate_request parent_req = *req; | ||
450 | 447 | ||
451 | /* if NO_REPARENT flag set, pass through to current parent */ | 448 | /* if NO_REPARENT flag set, pass through to current parent */ |
452 | if (core->flags & CLK_SET_RATE_NO_REPARENT) { | 449 | if (core->flags & CLK_SET_RATE_NO_REPARENT) { |
453 | parent = core->parent; | 450 | parent = core->parent; |
454 | if (core->flags & CLK_SET_RATE_PARENT) | 451 | if (core->flags & CLK_SET_RATE_PARENT) { |
455 | best = __clk_determine_rate(parent ? parent->hw : NULL, | 452 | ret = __clk_determine_rate(parent ? parent->hw : NULL, |
456 | rate, min_rate, max_rate); | 453 | &parent_req); |
457 | else if (parent) | 454 | if (ret) |
455 | return ret; | ||
456 | |||
457 | best = parent_req.rate; | ||
458 | } else if (parent) { | ||
458 | best = clk_core_get_rate_nolock(parent); | 459 | best = clk_core_get_rate_nolock(parent); |
459 | else | 460 | } else { |
460 | best = clk_core_get_rate_nolock(core); | 461 | best = clk_core_get_rate_nolock(core); |
462 | } | ||
463 | |||
461 | goto out; | 464 | goto out; |
462 | } | 465 | } |
463 | 466 | ||
@@ -467,24 +470,33 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, | |||
467 | parent = clk_core_get_parent_by_index(core, i); | 470 | parent = clk_core_get_parent_by_index(core, i); |
468 | if (!parent) | 471 | if (!parent) |
469 | continue; | 472 | continue; |
470 | if (core->flags & CLK_SET_RATE_PARENT) | 473 | |
471 | parent_rate = __clk_determine_rate(parent->hw, rate, | 474 | if (core->flags & CLK_SET_RATE_PARENT) { |
472 | min_rate, | 475 | parent_req = *req; |
473 | max_rate); | 476 | ret = __clk_determine_rate(parent->hw, &parent_req); |
474 | else | 477 | if (ret) |
475 | parent_rate = clk_core_get_rate_nolock(parent); | 478 | continue; |
476 | if (mux_is_better_rate(rate, parent_rate, best, flags)) { | 479 | } else { |
480 | parent_req.rate = clk_core_get_rate_nolock(parent); | ||
481 | } | ||
482 | |||
483 | if (mux_is_better_rate(req->rate, parent_req.rate, | ||
484 | best, flags)) { | ||
477 | best_parent = parent; | 485 | best_parent = parent; |
478 | best = parent_rate; | 486 | best = parent_req.rate; |
479 | } | 487 | } |
480 | } | 488 | } |
481 | 489 | ||
490 | if (!best_parent) | ||
491 | return -EINVAL; | ||
492 | |||
482 | out: | 493 | out: |
483 | if (best_parent) | 494 | if (best_parent) |
484 | *best_parent_p = best_parent->hw; | 495 | req->best_parent_hw = best_parent->hw; |
485 | *best_parent_rate = best; | 496 | req->best_parent_rate = best; |
497 | req->rate = best; | ||
486 | 498 | ||
487 | return best; | 499 | return 0; |
488 | } | 500 | } |
489 | 501 | ||
490 | struct clk *__clk_lookup(const char *name) | 502 | struct clk *__clk_lookup(const char *name) |
@@ -515,28 +527,17 @@ static void clk_core_get_boundaries(struct clk_core *core, | |||
515 | * directly as a determine_rate callback (e.g. for a mux), or from a more | 527 | * directly as a determine_rate callback (e.g. for a mux), or from a more |
516 | * complex clock that may combine a mux with other operations. | 528 | * complex clock that may combine a mux with other operations. |
517 | */ | 529 | */ |
518 | long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate, | 530 | int __clk_mux_determine_rate(struct clk_hw *hw, |
519 | unsigned long min_rate, | 531 | struct clk_rate_request *req) |
520 | unsigned long max_rate, | ||
521 | unsigned long *best_parent_rate, | ||
522 | struct clk_hw **best_parent_p) | ||
523 | { | 532 | { |
524 | return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate, | 533 | return clk_mux_determine_rate_flags(hw, req, 0); |
525 | best_parent_rate, | ||
526 | best_parent_p, 0); | ||
527 | } | 534 | } |
528 | EXPORT_SYMBOL_GPL(__clk_mux_determine_rate); | 535 | EXPORT_SYMBOL_GPL(__clk_mux_determine_rate); |
529 | 536 | ||
530 | long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, | 537 | int __clk_mux_determine_rate_closest(struct clk_hw *hw, |
531 | unsigned long min_rate, | 538 | struct clk_rate_request *req) |
532 | unsigned long max_rate, | ||
533 | unsigned long *best_parent_rate, | ||
534 | struct clk_hw **best_parent_p) | ||
535 | { | 539 | { |
536 | return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate, | 540 | return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST); |
537 | best_parent_rate, | ||
538 | best_parent_p, | ||
539 | CLK_MUX_ROUND_CLOSEST); | ||
540 | } | 541 | } |
541 | EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); | 542 | EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); |
542 | 543 | ||
@@ -759,14 +760,11 @@ int clk_enable(struct clk *clk) | |||
759 | } | 760 | } |
760 | EXPORT_SYMBOL_GPL(clk_enable); | 761 | EXPORT_SYMBOL_GPL(clk_enable); |
761 | 762 | ||
762 | static unsigned long clk_core_round_rate_nolock(struct clk_core *core, | 763 | static int clk_core_round_rate_nolock(struct clk_core *core, |
763 | unsigned long rate, | 764 | struct clk_rate_request *req) |
764 | unsigned long min_rate, | ||
765 | unsigned long max_rate) | ||
766 | { | 765 | { |
767 | unsigned long parent_rate = 0; | ||
768 | struct clk_core *parent; | 766 | struct clk_core *parent; |
769 | struct clk_hw *parent_hw; | 767 | long rate; |
770 | 768 | ||
771 | lockdep_assert_held(&prepare_lock); | 769 | lockdep_assert_held(&prepare_lock); |
772 | 770 | ||
@@ -774,21 +772,30 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core, | |||
774 | return 0; | 772 | return 0; |
775 | 773 | ||
776 | parent = core->parent; | 774 | parent = core->parent; |
777 | if (parent) | 775 | if (parent) { |
778 | parent_rate = parent->rate; | 776 | req->best_parent_hw = parent->hw; |
777 | req->best_parent_rate = parent->rate; | ||
778 | } else { | ||
779 | req->best_parent_hw = NULL; | ||
780 | req->best_parent_rate = 0; | ||
781 | } | ||
779 | 782 | ||
780 | if (core->ops->determine_rate) { | 783 | if (core->ops->determine_rate) { |
781 | parent_hw = parent ? parent->hw : NULL; | 784 | return core->ops->determine_rate(core->hw, req); |
782 | return core->ops->determine_rate(core->hw, rate, | 785 | } else if (core->ops->round_rate) { |
783 | min_rate, max_rate, | 786 | rate = core->ops->round_rate(core->hw, req->rate, |
784 | &parent_rate, &parent_hw); | 787 | &req->best_parent_rate); |
785 | } else if (core->ops->round_rate) | 788 | if (rate < 0) |
786 | return core->ops->round_rate(core->hw, rate, &parent_rate); | 789 | return rate; |
787 | else if (core->flags & CLK_SET_RATE_PARENT) | 790 | |
788 | return clk_core_round_rate_nolock(core->parent, rate, min_rate, | 791 | req->rate = rate; |
789 | max_rate); | 792 | } else if (core->flags & CLK_SET_RATE_PARENT) { |
790 | else | 793 | return clk_core_round_rate_nolock(parent, req); |
791 | return core->rate; | 794 | } else { |
795 | req->rate = core->rate; | ||
796 | } | ||
797 | |||
798 | return 0; | ||
792 | } | 799 | } |
793 | 800 | ||
794 | /** | 801 | /** |
@@ -800,15 +807,14 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core, | |||
800 | * | 807 | * |
801 | * Useful for clk_ops such as .set_rate and .determine_rate. | 808 | * Useful for clk_ops such as .set_rate and .determine_rate. |
802 | */ | 809 | */ |
803 | unsigned long __clk_determine_rate(struct clk_hw *hw, | 810 | int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) |
804 | unsigned long rate, | ||
805 | unsigned long min_rate, | ||
806 | unsigned long max_rate) | ||
807 | { | 811 | { |
808 | if (!hw) | 812 | if (!hw) { |
813 | req->rate = 0; | ||
809 | return 0; | 814 | return 0; |
815 | } | ||
810 | 816 | ||
811 | return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate); | 817 | return clk_core_round_rate_nolock(hw->core, req); |
812 | } | 818 | } |
813 | EXPORT_SYMBOL_GPL(__clk_determine_rate); | 819 | EXPORT_SYMBOL_GPL(__clk_determine_rate); |
814 | 820 | ||
@@ -821,15 +827,20 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate); | |||
821 | */ | 827 | */ |
822 | unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) | 828 | unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) |
823 | { | 829 | { |
824 | unsigned long min_rate; | 830 | struct clk_rate_request req; |
825 | unsigned long max_rate; | 831 | int ret; |
826 | 832 | ||
827 | if (!clk) | 833 | if (!clk) |
828 | return 0; | 834 | return 0; |
829 | 835 | ||
830 | clk_core_get_boundaries(clk->core, &min_rate, &max_rate); | 836 | clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate); |
837 | req.rate = rate; | ||
838 | |||
839 | ret = clk_core_round_rate_nolock(clk->core, &req); | ||
840 | if (ret) | ||
841 | return 0; | ||
831 | 842 | ||
832 | return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate); | 843 | return req.rate; |
833 | } | 844 | } |
834 | EXPORT_SYMBOL_GPL(__clk_round_rate); | 845 | EXPORT_SYMBOL_GPL(__clk_round_rate); |
835 | 846 | ||
@@ -1249,7 +1260,6 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, | |||
1249 | { | 1260 | { |
1250 | struct clk_core *top = core; | 1261 | struct clk_core *top = core; |
1251 | struct clk_core *old_parent, *parent; | 1262 | struct clk_core *old_parent, *parent; |
1252 | struct clk_hw *parent_hw; | ||
1253 | unsigned long best_parent_rate = 0; | 1263 | unsigned long best_parent_rate = 0; |
1254 | unsigned long new_rate; | 1264 | unsigned long new_rate; |
1255 | unsigned long min_rate; | 1265 | unsigned long min_rate; |
@@ -1270,20 +1280,29 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, | |||
1270 | 1280 | ||
1271 | /* find the closest rate and parent clk/rate */ | 1281 | /* find the closest rate and parent clk/rate */ |
1272 | if (core->ops->determine_rate) { | 1282 | if (core->ops->determine_rate) { |
1273 | parent_hw = parent ? parent->hw : NULL; | 1283 | struct clk_rate_request req; |
1274 | ret = core->ops->determine_rate(core->hw, rate, | 1284 | |
1275 | min_rate, | 1285 | req.rate = rate; |
1276 | max_rate, | 1286 | req.min_rate = min_rate; |
1277 | &best_parent_rate, | 1287 | req.max_rate = max_rate; |
1278 | &parent_hw); | 1288 | if (parent) { |
1289 | req.best_parent_hw = parent->hw; | ||
1290 | req.best_parent_rate = parent->rate; | ||
1291 | } else { | ||
1292 | req.best_parent_hw = NULL; | ||
1293 | req.best_parent_rate = 0; | ||
1294 | } | ||
1295 | |||
1296 | ret = core->ops->determine_rate(core->hw, &req); | ||
1279 | if (ret < 0) | 1297 | if (ret < 0) |
1280 | return NULL; | 1298 | return NULL; |
1281 | 1299 | ||
1282 | new_rate = ret; | 1300 | best_parent_rate = req.best_parent_rate; |
1283 | parent = parent_hw ? parent_hw->core : NULL; | 1301 | new_rate = req.rate; |
1302 | parent = req.best_parent_hw ? req.best_parent_hw->core : NULL; | ||
1284 | } else if (core->ops->round_rate) { | 1303 | } else if (core->ops->round_rate) { |
1285 | ret = core->ops->round_rate(core->hw, rate, | 1304 | ret = core->ops->round_rate(core->hw, rate, |
1286 | &best_parent_rate); | 1305 | &best_parent_rate); |
1287 | if (ret < 0) | 1306 | if (ret < 0) |
1288 | return NULL; | 1307 | return NULL; |
1289 | 1308 | ||