summaryrefslogtreecommitdiff
path: root/drivers/clk/sunxi-ng/ccu_mux.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2017-05-17 10:40:36 +0300
committerMaxime Ripard <maxime.ripard@free-electrons.com>2017-06-07 16:32:14 +0300
commitabea24218aa9e40e504d89ac1b7c6b4588a6cd9b (patch)
tree2398c6300d531288c1babade1ab3be3ea91c11fb /drivers/clk/sunxi-ng/ccu_mux.c
parentd754b15951ffe3c85e2581eaa244ed4a82080970 (diff)
downloadlinux-abea24218aa9e40e504d89ac1b7c6b4588a6cd9b.tar.xz
clk: sunxi-ng: mux: Re-adjust parent rate
Currently, the parent rate given back to the clock framework in our request is the original parent rate we calculated before trying to round the rate of our clock. This works fine unless our clock also changes its parent rate, in which case we will simply ignore that change and still use the previous parent rate. Create a new function to re-adjust the parent rate to take the pre-dividers into account, and give that back to the clock framework. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Diffstat (limited to 'drivers/clk/sunxi-ng/ccu_mux.c')
-rw-r--r--drivers/clk/sunxi-ng/ccu_mux.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index c33210972581..748b172f9193 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -64,6 +64,14 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
return parent_rate / ccu_mux_get_prediv(common, cm, parent_index);
}
+unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
+ struct ccu_mux_internal *cm,
+ int parent_index,
+ unsigned long parent_rate)
+{
+ return parent_rate * ccu_mux_get_prediv(common, cm, parent_index);
+}
+
int ccu_mux_helper_determine_rate(struct ccu_common *common,
struct ccu_mux_internal *cm,
struct clk_rate_request *req,
@@ -89,22 +97,37 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
best_rate = round(cm, best_parent, &adj_parent_rate,
req->rate, data);
+ /*
+ * adj_parent_rate might have been modified by our clock.
+ * Unapply the pre-divider if there's one, and give
+ * the actual frequency the parent needs to run at.
+ */
+ best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1,
+ adj_parent_rate);
+
goto out;
}
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
- unsigned long tmp_rate, parent_rate, adj_parent_rate;
+ unsigned long tmp_rate, parent_rate;
struct clk_hw *parent;
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
- parent_rate = clk_hw_get_rate(parent);
- adj_parent_rate = ccu_mux_helper_apply_prediv(common, cm, i,
- parent_rate);
+ parent_rate = ccu_mux_helper_apply_prediv(common, cm, i,
+ clk_hw_get_rate(parent));
+
+ tmp_rate = round(cm, parent, &parent_rate, req->rate, data);
- tmp_rate = round(cm, parent, &adj_parent_rate, req->rate, data);
+ /*
+ * parent_rate might have been modified by our clock.
+ * Unapply the pre-divider if there's one, and give
+ * the actual frequency the parent needs to run at.
+ */
+ parent_rate = ccu_mux_helper_unapply_prediv(common, cm, i,
+ parent_rate);
if (tmp_rate == req->rate) {
best_parent = parent;
best_parent_rate = parent_rate;