aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.com>2015-01-23 06:03:31 -0500
committerMichael Turquette <mturquette@linaro.org>2015-02-02 17:23:42 -0500
commit1c8e600440c7f5036bd9a94526d01e9c7cb68dca (patch)
tree36c9811e976332bc23a00a6fb216dce5e6b55a5a /drivers
parentb09d6d99102504a929cfaba4cd0e07658d7f01d1 (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.c2
-rw-r--r--drivers/clk/bcm/clk-kona.c2
-rw-r--r--drivers/clk/clk-composite.c9
-rw-r--r--drivers/clk/clk.c272
-rw-r--r--drivers/clk/hisilicon/clk-hi3620.c2
-rw-r--r--drivers/clk/mmp/clk-mix.c2
-rw-r--r--drivers/clk/qcom/clk-pll.c1
-rw-r--r--drivers/clk/qcom/clk-rcg.c10
-rw-r--r--drivers/clk/qcom/clk-rcg2.c6
-rw-r--r--drivers/clk/sunxi/clk-factors.c2
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c2
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c2
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
57static long clk_programmable_determine_rate(struct clk_hw *hw, 57static 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
1034static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate, 1034static 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
58static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, 58static 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);
42static int clk_core_get_phase(struct clk_core *clk); 42static int clk_core_get_phase(struct clk_core *clk);
43static bool clk_core_is_prepared(struct clk_core *clk); 43static bool clk_core_is_prepared(struct clk_core *clk);
44static bool clk_core_is_enabled(struct clk_core *clk); 44static bool clk_core_is_enabled(struct clk_core *clk);
45static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
46 unsigned long rate);
47static struct clk_core *clk_core_lookup(const char *name); 45static 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
784static long 787static long
785clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate, 788clk_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
845static 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)