mirror of https://gitee.com/openkylin/linux.git
clk: renesas: div6: Consider all parents for requested rate
Currently the .determine_rate() callback considers only the current parent clock, limiting the range of achievable clock rates on DIV6 clocks with multiple parents, as found on SH/R-Mobile SoCs. Extend the callback to consider all available parent clocks. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/r/60e639692b462f99e0b6ab868c3675b3d97dbdb0.1617281699.git.geert+renesas@glider.be
This commit is contained in:
parent
c9d1b58b27
commit
1c924fc679
|
@ -103,10 +103,39 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
|
|||
static int cpg_div6_clock_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned int div = cpg_div6_clock_calc_div(req->rate,
|
||||
req->best_parent_rate);
|
||||
unsigned long prate, calc_rate, diff, best_rate, best_prate;
|
||||
unsigned int num_parents = clk_hw_get_num_parents(hw);
|
||||
struct clk_hw *parent, *best_parent = NULL;
|
||||
unsigned long min_diff = ULONG_MAX;
|
||||
unsigned int i, div;
|
||||
|
||||
req->rate = req->best_parent_rate / div;
|
||||
for (i = 0; i < num_parents; i++) {
|
||||
parent = clk_hw_get_parent_by_index(hw, i);
|
||||
if (!parent)
|
||||
continue;
|
||||
|
||||
prate = clk_hw_get_rate(parent);
|
||||
if (!prate)
|
||||
continue;
|
||||
|
||||
div = cpg_div6_clock_calc_div(req->rate, prate);
|
||||
calc_rate = prate / div;
|
||||
diff = calc_rate > req->rate ? calc_rate - req->rate
|
||||
: req->rate - calc_rate;
|
||||
if (diff < min_diff) {
|
||||
best_rate = calc_rate;
|
||||
best_parent = parent;
|
||||
best_prate = prate;
|
||||
min_diff = diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_parent)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_rate = best_prate;
|
||||
req->best_parent_hw = best_parent;
|
||||
req->rate = best_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue