diff options
| author | Tomeu Vizoso <tomeu.vizoso@collabora.com> | 2015-01-23 06:03:31 -0500 |
|---|---|---|
| committer | Michael Turquette <mturquette@linaro.org> | 2015-02-02 17:23:42 -0500 |
| commit | 1c8e600440c7f5036bd9a94526d01e9c7cb68dca (patch) | |
| tree | 36c9811e976332bc23a00a6fb216dce5e6b55a5a /drivers | |
| parent | b09d6d99102504a929cfaba4cd0e07658d7f01d1 (diff) | |
clk: Add rate constraints to clocks
Adds a way for clock consumers to set maximum and minimum rates. This
can be used for thermal drivers to set minimum rates, or by misc.
drivers to set maximum rates to assure a minimum performance level.
Changes the signature of the determine_rate callback by adding the
parameters min_rate and max_rate.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
[sboyd@codeaurora.org: set req_rate in __clk_init]
Signed-off-by: Michael Turquette <mturquette@linaro.org>
[mturquette@linaro.org: min/max rate for sun6i_ahb1_clk_determine_rate
migrated clk-private.h changes to clk.c]
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/at91/clk-programmable.c | 2 | ||||
| -rw-r--r-- | drivers/clk/bcm/clk-kona.c | 2 | ||||
| -rw-r--r-- | drivers/clk/clk-composite.c | 9 | ||||
| -rw-r--r-- | drivers/clk/clk.c | 272 | ||||
| -rw-r--r-- | drivers/clk/hisilicon/clk-hi3620.c | 2 | ||||
| -rw-r--r-- | drivers/clk/mmp/clk-mix.c | 2 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-pll.c | 1 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-rcg.c | 10 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-rcg2.c | 6 | ||||
| -rw-r--r-- | drivers/clk/sunxi/clk-factors.c | 2 | ||||
| -rw-r--r-- | drivers/clk/sunxi/clk-sun6i-ar100.c | 2 | ||||
| -rw-r--r-- | drivers/clk/sunxi/clk-sunxi.c | 2 |
12 files changed, 254 insertions, 58 deletions
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index bbdb1b985c91..86c8a073dcc3 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c | |||
| @@ -56,6 +56,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, | |||
| 56 | 56 | ||
| 57 | static long clk_programmable_determine_rate(struct clk_hw *hw, | 57 | static long clk_programmable_determine_rate(struct clk_hw *hw, |
| 58 | unsigned long rate, | 58 | unsigned long rate, |
| 59 | unsigned long min_rate, | ||
| 60 | unsigned long max_rate, | ||
| 59 | unsigned long *best_parent_rate, | 61 | unsigned long *best_parent_rate, |
| 60 | struct clk_hw **best_parent_hw) | 62 | struct clk_hw **best_parent_hw) |
| 61 | { | 63 | { |
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index 1c06f6f3a8c5..05abae89262e 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c | |||
| @@ -1032,6 +1032,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 1032 | } | 1032 | } |
| 1033 | 1033 | ||
| 1034 | static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | 1034 | static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, |
| 1035 | unsigned long min_rate, | ||
| 1036 | unsigned long max_rate, | ||
| 1035 | unsigned long *best_parent_rate, struct clk_hw **best_parent) | 1037 | unsigned long *best_parent_rate, struct clk_hw **best_parent) |
| 1036 | { | 1038 | { |
| 1037 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 1039 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 4386697236a7..dee81b83c4b3 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c | |||
| @@ -56,6 +56,8 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | 58 | static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, |
| 59 | unsigned long min_rate, | ||
| 60 | unsigned long max_rate, | ||
| 59 | unsigned long *best_parent_rate, | 61 | unsigned long *best_parent_rate, |
| 60 | struct clk_hw **best_parent_p) | 62 | struct clk_hw **best_parent_p) |
| 61 | { | 63 | { |
| @@ -73,7 +75,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
| 73 | 75 | ||
| 74 | if (rate_hw && rate_ops && rate_ops->determine_rate) { | 76 | if (rate_hw && rate_ops && rate_ops->determine_rate) { |
| 75 | rate_hw->clk = hw->clk; | 77 | rate_hw->clk = hw->clk; |
| 76 | return rate_ops->determine_rate(rate_hw, rate, best_parent_rate, | 78 | return rate_ops->determine_rate(rate_hw, rate, min_rate, |
| 79 | max_rate, | ||
| 80 | best_parent_rate, | ||
| 77 | best_parent_p); | 81 | best_parent_p); |
| 78 | } else if (rate_hw && rate_ops && rate_ops->round_rate && | 82 | } else if (rate_hw && rate_ops && rate_ops->round_rate && |
| 79 | mux_hw && mux_ops && mux_ops->set_parent) { | 83 | mux_hw && mux_ops && mux_ops->set_parent) { |
| @@ -117,7 +121,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | |||
| 117 | return best_rate; | 121 | return best_rate; |
| 118 | } else if (mux_hw && mux_ops && mux_ops->determine_rate) { | 122 | } else if (mux_hw && mux_ops && mux_ops->determine_rate) { |
| 119 | mux_hw->clk = hw->clk; | 123 | mux_hw->clk = hw->clk; |
| 120 | return mux_ops->determine_rate(mux_hw, rate, best_parent_rate, | 124 | return mux_ops->determine_rate(mux_hw, rate, min_rate, |
| 125 | max_rate, best_parent_rate, | ||
| 121 | best_parent_p); | 126 | best_parent_p); |
| 122 | } else { | 127 | } else { |
| 123 | pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); | 128 | pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index cdc1fa58e4f1..113456030d66 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -42,8 +42,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk); | |||
| 42 | static int clk_core_get_phase(struct clk_core *clk); | 42 | static int clk_core_get_phase(struct clk_core *clk); |
| 43 | static bool clk_core_is_prepared(struct clk_core *clk); | 43 | static bool clk_core_is_prepared(struct clk_core *clk); |
| 44 | static bool clk_core_is_enabled(struct clk_core *clk); | 44 | static bool clk_core_is_enabled(struct clk_core *clk); |
| 45 | static unsigned long clk_core_round_rate_nolock(struct clk_core *clk, | ||
| 46 | unsigned long rate); | ||
| 47 | static struct clk_core *clk_core_lookup(const char *name); | 45 | static struct clk_core *clk_core_lookup(const char *name); |
| 48 | 46 | ||
| 49 | /*** private data structures ***/ | 47 | /*** private data structures ***/ |
| @@ -59,6 +57,7 @@ struct clk_core { | |||
| 59 | u8 num_parents; | 57 | u8 num_parents; |
| 60 | u8 new_parent_index; | 58 | u8 new_parent_index; |
| 61 | unsigned long rate; | 59 | unsigned long rate; |
| 60 | unsigned long req_rate; | ||
| 62 | unsigned long new_rate; | 61 | unsigned long new_rate; |
| 63 | struct clk_core *new_parent; | 62 | struct clk_core *new_parent; |
| 64 | struct clk_core *new_child; | 63 | struct clk_core *new_child; |
| @@ -70,6 +69,7 @@ struct clk_core { | |||
| 70 | struct hlist_head children; | 69 | struct hlist_head children; |
| 71 | struct hlist_node child_node; | 70 | struct hlist_node child_node; |
| 72 | struct hlist_node debug_node; | 71 | struct hlist_node debug_node; |
| 72 | struct hlist_head clks; | ||
| 73 | unsigned int notifier_count; | 73 | unsigned int notifier_count; |
| 74 | #ifdef CONFIG_DEBUG_FS | 74 | #ifdef CONFIG_DEBUG_FS |
| 75 | struct dentry *dentry; | 75 | struct dentry *dentry; |
| @@ -81,6 +81,9 @@ struct clk { | |||
| 81 | struct clk_core *core; | 81 | struct clk_core *core; |
| 82 | const char *dev_id; | 82 | const char *dev_id; |
| 83 | const char *con_id; | 83 | const char *con_id; |
| 84 | unsigned long min_rate; | ||
| 85 | unsigned long max_rate; | ||
| 86 | struct hlist_node child_node; | ||
| 84 | }; | 87 | }; |
| 85 | 88 | ||
| 86 | /*** locking ***/ | 89 | /*** locking ***/ |
| @@ -783,6 +786,8 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, | |||
| 783 | 786 | ||
| 784 | static long | 787 | static long |
| 785 | clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, | 788 | clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, |
| 789 | unsigned long min_rate, | ||
| 790 | unsigned long max_rate, | ||
| 786 | unsigned long *best_parent_rate, | 791 | unsigned long *best_parent_rate, |
| 787 | struct clk_hw **best_parent_p, | 792 | struct clk_hw **best_parent_p, |
| 788 | unsigned long flags) | 793 | unsigned long flags) |
| @@ -795,7 +800,8 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, | |||
| 795 | if (core->flags & CLK_SET_RATE_NO_REPARENT) { | 800 | if (core->flags & CLK_SET_RATE_NO_REPARENT) { |
| 796 | parent = core->parent; | 801 | parent = core->parent; |
| 797 | if (core->flags & CLK_SET_RATE_PARENT) | 802 | if (core->flags & CLK_SET_RATE_PARENT) |
| 798 | best = clk_core_round_rate_nolock(parent, rate); | 803 | best = __clk_determine_rate(parent->hw, rate, |
| 804 | min_rate, max_rate); | ||
| 799 | else if (parent) | 805 | else if (parent) |
| 800 | best = clk_core_get_rate_nolock(parent); | 806 | best = clk_core_get_rate_nolock(parent); |
| 801 | else | 807 | else |
| @@ -810,7 +816,9 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, | |||
| 810 | if (!parent) | 816 | if (!parent) |
| 811 | continue; | 817 | continue; |
| 812 | if (core->flags & CLK_SET_RATE_PARENT) | 818 | if (core->flags & CLK_SET_RATE_PARENT) |
| 813 | parent_rate = clk_core_round_rate_nolock(parent, rate); | 819 | parent_rate = __clk_determine_rate(parent->hw, rate, |
| 820 | min_rate, | ||
| 821 | max_rate); | ||
| 814 | else | 822 | else |
| 815 | parent_rate = clk_core_get_rate_nolock(parent); | 823 | parent_rate = clk_core_get_rate_nolock(parent); |
| 816 | if (mux_is_better_rate(rate, parent_rate, best, flags)) { | 824 | if (mux_is_better_rate(rate, parent_rate, best, flags)) { |
| @@ -834,25 +842,47 @@ struct clk *__clk_lookup(const char *name) | |||
| 834 | return !core ? NULL : core->hw->clk; | 842 | return !core ? NULL : core->hw->clk; |
| 835 | } | 843 | } |
| 836 | 844 | ||
| 845 | static void clk_core_get_boundaries(struct clk_core *clk, | ||
| 846 | unsigned long *min_rate, | ||
| 847 | unsigned long *max_rate) | ||
| 848 | { | ||
| 849 | struct clk *clk_user; | ||
| 850 | |||
| 851 | *min_rate = 0; | ||
| 852 | *max_rate = ULONG_MAX; | ||
| 853 | |||
| 854 | hlist_for_each_entry(clk_user, &clk->clks, child_node) | ||
| 855 | *min_rate = max(*min_rate, clk_user->min_rate); | ||
| 856 | |||
| 857 | hlist_for_each_entry(clk_user, &clk->clks, child_node) | ||
