diff options
author | Jerome Brunet <jbrunet@baylibre.com> | 2017-12-02 00:51:54 +0300 |
---|---|---|
committer | Michael Turquette <mturquette@baylibre.com> | 2017-12-20 03:17:43 +0300 |
commit | 0f6cc2b8e94da5400528c0ba7fd910392ec598a2 (patch) | |
tree | 3f2f13854af4eeb7875dacc4d4d62acb4641cfea /drivers/clk/clk.c | |
parent | 9e4d04adeb1a957be212aace20ac5cee6f14013c (diff) | |
download | linux-0f6cc2b8e94da5400528c0ba7fd910392ec598a2.tar.xz |
clk: rework calls to round and determine rate callbacks
Rework the way the callbacks round_rate() and determine_rate() are called.
The goal is to do this at a single point and make it easier to add
conditions before calling them.
Because of this factorization, rate returned by determine_rate() is also
checked against the min and max rate values
This rework is done to ease the integration of "protected" clock
functionality.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Tested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
Link: lkml.kernel.org/r/20171201215200.23523-5-jbrunet@baylibre.com
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7946a069ba2e..322d9ba7e5cd 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -905,10 +905,9 @@ static int clk_disable_unused(void) } late_initcall_sync(clk_disable_unused); -static int clk_core_round_rate_nolock(struct clk_core *core, - struct clk_rate_request *req) +static int clk_core_determine_round_nolock(struct clk_core *core, + struct clk_rate_request *req) { - struct clk_core *parent; long rate; lockdep_assert_held(&prepare_lock); @@ -916,15 +915,6 @@ static int clk_core_round_rate_nolock(struct clk_core *core, if (!core) return 0; - parent = core->parent; - if (parent) { - req->best_parent_hw = parent->hw; - req->best_parent_rate = parent->rate; - } else { - req->best_parent_hw = NULL; - req->best_parent_rate = 0; - } - if (core->ops->determine_rate) { return core->ops->determine_rate(core->hw, req); } else if (core->ops->round_rate) { @@ -934,15 +924,58 @@ static int clk_core_round_rate_nolock(struct clk_core *core, return rate; req->rate = rate; - } else if (core->flags & CLK_SET_RATE_PARENT) { - return clk_core_round_rate_nolock(parent, req); } else { - req->rate = core->rate; + return -EINVAL; } return 0; } +static void clk_core_init_rate_req(struct clk_core * const core, + struct clk_rate_request *req) +{ + struct clk_core *parent; + + if (WARN_ON(!core || !req)) + return; + + parent = core->parent; + if (parent) { + req->best_parent_hw = parent->hw; + req->best_parent_rate = parent->rate; + } else { + req->best_parent_hw = NULL; + req->best_parent_rate = 0; + } +} + +static bool clk_core_can_round(struct clk_core * const core) +{ + if (core->ops->determine_rate || core->ops->round_rate) + return true; + + return false; +} + +static int clk_core_round_rate_nolock(struct clk_core *core, + struct clk_rate_request *req) +{ + lockdep_assert_held(&prepare_lock); + + if (!core) + return 0; + + clk_core_init_rate_req(core, req); + + if (clk_core_can_round(core)) + return clk_core_determine_round_nolock(core, req); + else if (core->flags & CLK_SET_RATE_PARENT) + return clk_core_round_rate_nolock(core->parent, req); + + req->rate = core->rate; + return 0; +} + /** * __clk_determine_rate - get the closest rate actually supported by a clock * @hw: determine the rate of this clock @@ -1432,34 +1465,23 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, clk_core_get_boundaries(core, &min_rate, &max_rate); /* find the closest rate and parent clk/rate */ - if (core->ops->determine_rate) { + if (clk_core_can_round(core)) { struct clk_rate_request req; req.rate = rate; req.min_rate = min_rate; req.max_rate = max_rate; - if (parent) { - req.best_parent_hw = parent->hw; - req.best_parent_rate = parent->rate; - } else { - req.best_parent_hw = NULL; - req.best_parent_rate = 0; - } - ret = core->ops->determine_rate(core->hw, &req); + clk_core_init_rate_req(core, &req); + + ret = clk_core_determine_round_nolock(core, &req); if (ret < 0) return NULL; best_parent_rate = req.best_parent_rate; new_rate = req.rate; parent = req.best_parent_hw ? req.best_parent_hw->core : NULL; - } else if (core->ops->round_rate) { - ret = core->ops->round_rate(core->hw, rate, - &best_parent_rate); - if (ret < 0) - return NULL; - new_rate = ret; if (new_rate < min_rate || new_rate > max_rate) return NULL; } else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) { |