Merge branch 'clk-determine-rate-struct' into clk-next

* clk-determine-rate-struct:
  clk: fix some determine_rate implementations
  clk: change clk_ops' ->determine_rate() prototype
This commit is contained in:
Stephen Boyd
2015-07-28 11:51:30 -07:00
20 changed files with 412 additions and 405 deletions

View File

@@ -436,28 +436,31 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
return now <= rate && now > best;
}
static long
clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p,
static int
clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req,
unsigned long flags)
{
struct clk_core *core = hw->core, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0;
int i, num_parents, ret;
unsigned long best = 0;
struct clk_rate_request parent_req = *req;
/* if NO_REPARENT flag set, pass through to current parent */
if (core->flags & CLK_SET_RATE_NO_REPARENT) {
parent = core->parent;
if (core->flags & CLK_SET_RATE_PARENT)
best = __clk_determine_rate(parent ? parent->hw : NULL,
rate, min_rate, max_rate);
else if (parent)
if (core->flags & CLK_SET_RATE_PARENT) {
ret = __clk_determine_rate(parent ? parent->hw : NULL,
&parent_req);
if (ret)
return ret;
best = parent_req.rate;
} else if (parent) {
best = clk_core_get_rate_nolock(parent);
else
} else {
best = clk_core_get_rate_nolock(core);
}
goto out;
}
@@ -467,24 +470,33 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
parent = clk_core_get_parent_by_index(core, i);
if (!parent)
continue;
if (core->flags & CLK_SET_RATE_PARENT)
parent_rate = __clk_determine_rate(parent->hw, rate,
min_rate,
max_rate);
else
parent_rate = clk_core_get_rate_nolock(parent);
if (mux_is_better_rate(rate, parent_rate, best, flags)) {
if (core->flags & CLK_SET_RATE_PARENT) {
parent_req = *req;
ret = __clk_determine_rate(parent->hw, &parent_req);
if (ret)
continue;
} else {
parent_req.rate = clk_core_get_rate_nolock(parent);
}
if (mux_is_better_rate(req->rate, parent_req.rate,
best, flags)) {
best_parent = parent;
best = parent_rate;
best = parent_req.rate;
}
}
if (!best_parent)
return -EINVAL;
out:
if (best_parent)
*best_parent_p = best_parent->hw;
*best_parent_rate = best;
req->best_parent_hw = best_parent->hw;
req->best_parent_rate = best;
req->rate = best;
return best;
return 0;
}
struct clk *__clk_lookup(const char *name)
@@ -515,28 +527,17 @@ static void clk_core_get_boundaries(struct clk_core *core,
* directly as a determine_rate callback (e.g. for a mux), or from a more
* complex clock that may combine a mux with other operations.
*/
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
int __clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
best_parent_rate,
best_parent_p, 0);
return clk_mux_determine_rate_flags(hw, req, 0);
}
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
int __clk_mux_determine_rate_closest(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
best_parent_rate,
best_parent_p,
CLK_MUX_ROUND_CLOSEST);
return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
}
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
@@ -759,14 +760,11 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_enable);
static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate)
static int clk_core_round_rate_nolock(struct clk_core *core,
struct clk_rate_request *req)
{
unsigned long parent_rate = 0;
struct clk_core *parent;
struct clk_hw *parent_hw;
long rate;
lockdep_assert_held(&prepare_lock);
@@ -774,21 +772,30 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
return 0;
parent = core->parent;
if (parent)
parent_rate = parent->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;
}
if (core->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
return core->ops->determine_rate(core->hw, rate,
min_rate, max_rate,
&parent_rate, &parent_hw);
} else if (core->ops->round_rate)
return core->ops->round_rate(core->hw, rate, &parent_rate);
else if (core->flags & CLK_SET_RATE_PARENT)
return clk_core_round_rate_nolock(core->parent, rate, min_rate,
max_rate);
else
return core->rate;
return core->ops->determine_rate(core->hw, req);
} else if (core->ops->round_rate) {
rate = core->ops->round_rate(core->hw, req->rate,
&req->best_parent_rate);
if (rate < 0)
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 0;
}
/**
@@ -800,15 +807,14 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
*
* Useful for clk_ops such as .set_rate and .determine_rate.
*/
unsigned long __clk_determine_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long min_rate,
unsigned long max_rate)
int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
if (!hw)
if (!hw) {
req->rate = 0;
return 0;
}
return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
return clk_core_round_rate_nolock(hw->core, req);
}
EXPORT_SYMBOL_GPL(__clk_determine_rate);
@@ -821,15 +827,20 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate);
*/
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long min_rate;
unsigned long max_rate;
struct clk_rate_request req;
int ret;
if (!clk)
return 0;
clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
req.rate = rate;
return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
ret = clk_core_round_rate_nolock(clk->core, &req);
if (ret)
return 0;
return req.rate;
}
EXPORT_SYMBOL_GPL(__clk_round_rate);
@@ -1249,7 +1260,6 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
{
struct clk_core *top = core;
struct clk_core *old_parent, *parent;
struct clk_hw *parent_hw;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
unsigned long min_rate;
@@ -1270,20 +1280,29 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
/* find the closest rate and parent clk/rate */
if (core->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
ret = core->ops->determine_rate(core->hw, rate,
min_rate,
max_rate,
&best_parent_rate,
&parent_hw);
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);
if (ret < 0)
return NULL;
new_rate = ret;
parent = parent_hw ? parent_hw->core : 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);
&best_parent_rate);
if (ret < 0)
return NULL;