[PATCH 4/5] clk: renesas: div6: Consider all parents for requested rate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 drivers/clk/renesas/clk-div6.c | 35 +++++++++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c
index 3af65ef5690e3d84..a9ac2a83c1d0daa0 100644
--- a/drivers/clk/renesas/clk-div6.c
+++ b/drivers/clk/renesas/clk-div6.c
@@ -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;
+
+	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->rate = req->best_parent_rate / div;
+	req->best_parent_rate = best_prate;
+	req->best_parent_hw = best_parent;
+	req->rate = best_rate;
 	return 0;
 }
 
-- 
2.25.1




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux