mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-03 09:04:21 +08:00
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
This commit is contained in:
parent
9e4d04adeb
commit
0f6cc2b8e9
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user