diff options
author | Quentin Schulz <quentin.schulz@free-electrons.com> | 2017-08-10 02:34:04 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2017-09-01 18:46:53 -0400 |
commit | 8a8f4bf0c48055f0648b5449f4685b6cd0fc1c85 (patch) | |
tree | 925f18e24acecef715ed485e7a5f76d074ac13ad | |
parent | 0865805d82d4c822647ee35ab2629c48cc40706b (diff) |
clk: at91: clk-generated: create function to find best_diff
The way to find the best_diff and do the appropriate process afterwards
can be re-used.
This patch prepares the driver for an upcoming patch that will allow
clk_generated to determine the rate of the audio_pll.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/at91/clk-generated.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index ef4b4e03de04..7260e498e059 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c | |||
@@ -99,15 +99,36 @@ clk_generated_recalc_rate(struct clk_hw *hw, | |||
99 | return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1); | 99 | return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1); |
100 | } | 100 | } |
101 | 101 | ||
102 | static void clk_generated_best_diff(struct clk_rate_request *req, | ||
103 | struct clk_hw *parent, | ||
104 | unsigned long parent_rate, u32 div, | ||
105 | int *best_diff, long *best_rate) | ||
106 | { | ||
107 | unsigned long tmp_rate; | ||
108 | int tmp_diff; | ||
109 | |||
110 | if (!div) | ||
111 | tmp_rate = parent_rate; | ||
112 | else | ||
113 | tmp_rate = parent_rate / div; | ||
114 | tmp_diff = abs(req->rate - tmp_rate); | ||
115 | |||
116 | if (*best_diff < 0 || *best_diff > tmp_diff) { | ||
117 | *best_rate = tmp_rate; | ||
118 | *best_diff = tmp_diff; | ||
119 | req->best_parent_rate = parent_rate; | ||
120 | req->best_parent_hw = parent; | ||
121 | } | ||
122 | } | ||
123 | |||
102 | static int clk_generated_determine_rate(struct clk_hw *hw, | 124 | static int clk_generated_determine_rate(struct clk_hw *hw, |
103 | struct clk_rate_request *req) | 125 | struct clk_rate_request *req) |
104 | { | 126 | { |
105 | struct clk_generated *gck = to_clk_generated(hw); | 127 | struct clk_generated *gck = to_clk_generated(hw); |
106 | struct clk_hw *parent = NULL; | 128 | struct clk_hw *parent = NULL; |
107 | long best_rate = -EINVAL; | 129 | long best_rate = -EINVAL; |
108 | unsigned long tmp_rate, min_rate; | 130 | unsigned long min_rate; |
109 | int best_diff = -1; | 131 | int best_diff = -1; |
110 | int tmp_diff; | ||
111 | int i; | 132 | int i; |
112 | 133 | ||
113 | for (i = 0; i < clk_hw_get_num_parents(hw); i++) { | 134 | for (i = 0; i < clk_hw_get_num_parents(hw); i++) { |
@@ -125,18 +146,10 @@ static int clk_generated_determine_rate(struct clk_hw *hw, | |||
125 | continue; | 146 | continue; |
126 | 147 | ||
127 | div = DIV_ROUND_CLOSEST(parent_rate, req->rate); | 148 | div = DIV_ROUND_CLOSEST(parent_rate, req->rate); |
128 | if (!div) | 149 | |
129 | tmp_rate = parent_rate; | 150 | clk_generated_best_diff(req, parent, parent_rate, div, |
130 | else | 151 | &best_diff, &best_rate); |
131 | tmp_rate = parent_rate / div; | 152 | |
132 | tmp_diff = abs(req->rate - tmp_rate); | ||
133 | |||
134 | if (best_diff < 0 || best_diff > tmp_diff) { | ||
135 | best_rate = tmp_rate; | ||
136 | best_diff = tmp_diff; | ||
137 | req->best_parent_rate = parent_rate; | ||
138 | req->best_parent_hw = parent; | ||
139 | } | ||
140 | 153 | ||
141 | if (!best_diff) | 154 | if (!best_diff) |
142 | break; | 155 | break; |