mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] clk: clk-mux: implement setting rate by reparenting
@ 2021-06-07 12:19 Sascha Hauer
  2021-06-07 12:19 ` [PATCH 2/2] clk: clk-composite: " Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Sascha Hauer @ 2021-06-07 12:19 UTC (permalink / raw)
  To: Barebox List

This implements rate setting for the generic clk mux by reparenting to
the best parent clock. Like in Linux we only do this when the
CLK_SET_RATE_NO_REPARENT flag is not set.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-mux.c | 82 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 80 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index e7e4369ce0..d8c09e4a75 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -41,9 +41,87 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 idx)
 	return 0;
 }
 
+static struct clk *clk_get_parent_index(struct clk *clk, int num)
+{
+	if (num >= clk->num_parents)
+		return NULL;
+
+	if (clk->parents[num])
+		return clk->parents[num];
+
+	clk->parents[num] = clk_lookup(clk->parent_names[num]);
+
+	return clk->parents[num];
+}
+
+static struct clk *clk_mux_best_parent(struct clk *mux, unsigned long rate,
+	unsigned long *rrate)
+{
+	struct clk *bestparent = NULL;
+	long bestrate = LONG_MAX;
+	int i;
+
+	for (i = 0; i < mux->num_parents; i++) {
+		struct clk *parent = clk_get_parent_index(mux, i);
+		unsigned long r;
+
+		if (IS_ERR_OR_NULL(parent))
+			continue;
+
+		if (mux->flags & CLK_SET_RATE_PARENT)
+			r = clk_round_rate(parent, rate);
+		else
+			r = clk_get_rate(parent);
+
+		if (abs((long)rate - r) < abs((long)rate - bestrate)) {
+			bestrate = r;
+			bestparent = parent;
+		}
+	}
+
+	*rrate = bestrate;
+
+	return bestparent;
+}
+
+static long clk_mux_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *prate)
+{
+	struct clk *clk = clk_hw_to_clk(hw);
+	unsigned long rrate;
+	struct clk *bestparent;
+
+	if (clk->flags & CLK_SET_RATE_NO_REPARENT)
+		return *prate;
+
+	bestparent = clk_mux_best_parent(clk, rate, &rrate);
+
+	return rrate;
+}
+
+static int clk_mux_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct clk *clk = clk_hw_to_clk(hw);
+	struct clk *parent;
+	unsigned long rrate;
+	int ret;
+
+	if (clk->flags & CLK_SET_RATE_NO_REPARENT)
+		return 0;
+
+	parent = clk_mux_best_parent(clk, rate, &rrate);
+
+	ret = clk_set_parent(clk, parent);
+	if (ret)
+		return ret;
+
+	return clk_set_rate(parent, rate);
+}
+
 const struct clk_ops clk_mux_ops = {
-	.set_rate = clk_parent_set_rate,
-	.round_rate = clk_parent_round_rate,
+	.set_rate = clk_mux_set_rate,
+	.round_rate = clk_mux_round_rate,
 	.get_parent = clk_mux_get_parent,
 	.set_parent = clk_mux_set_parent,
 };
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 2/2] clk: clk-composite: implement setting rate by reparenting
  2021-06-07 12:19 [PATCH 1/2] clk: clk-mux: implement setting rate by reparenting Sascha Hauer
@ 2021-06-07 12:19 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2021-06-07 12:19 UTC (permalink / raw)
  To: Barebox List

Support setting the clock rate by reparenting the mux clock. For now
only use the mux clock for setting the rate when the rate clock is not
present. Using both clocks for finding the best rate is left as a future
exercise.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-composite.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 3ed628c919..479ac5e8ef 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -57,9 +57,18 @@ static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_composite *composite = to_clk_composite(hw);
 	struct clk *rate_clk = composite->rate_clk;
+	struct clk *mux_clk = composite->mux_clk;
 	struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk);
 
-	return rate_clk ? rate_clk->ops->round_rate(rate_hw, rate, prate) : 0;
+	if (rate_clk)
+		return rate_clk->ops->round_rate(rate_hw, rate, prate);
+
+	if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) &&
+	    mux_clk &&
+	    mux_clk->ops->set_rate)
+		return mux_clk->ops->round_rate(clk_to_clk_hw(mux_clk), rate, prate);
+
+	return *prate;
 }
 
 static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -67,10 +76,23 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_composite *composite = to_clk_composite(hw);
 	struct clk *rate_clk = composite->rate_clk;
+	struct clk *mux_clk = composite->mux_clk;
 	struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk);
 
-	return rate_clk ?
-		rate_clk->ops->set_rate(rate_hw, rate, parent_rate) : 0;
+	/*
+	 * When the rate clock is present use that to set the rate,
+	 * otherwise try the mux clock. We currently do not support
+	 * to find the best rate using a combination of both.
+	 */
+	if (rate_clk)
+		return rate_clk->ops->set_rate(rate_hw, rate, parent_rate);
+
+	if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) &&
+	    mux_clk &&
+	    mux_clk->ops->set_rate)
+		return mux_clk->ops->set_rate(clk_to_clk_hw(mux_clk), rate, parent_rate);
+
+	return 0;
 }
 
 static int clk_composite_is_enabled(struct clk_hw *hw)
@@ -137,6 +159,12 @@ struct clk *clk_register_composite(const char *name,
 	if (ret)
 		goto err;
 
+	if (composite->mux_clk) {
+		composite->mux_clk->parents = composite->hw.clk.parents;
+		composite->mux_clk->parent_names = composite->hw.clk.parent_names;
+		composite->mux_clk->num_parents = composite->hw.clk.num_parents;
+	}
+
 	return &composite->hw.clk;
 
 err:
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-06-07 12:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-07 12:19 [PATCH 1/2] clk: clk-mux: implement setting rate by reparenting Sascha Hauer
2021-06-07 12:19 ` [PATCH 2/2] clk: clk-composite: " Sascha Hauer

mail archive of the barebox mailing list

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://lore.barebox.org/barebox/0 barebox/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 barebox barebox/ https://lore.barebox.org/barebox \
		barebox@lists.infradead.org barebox@lists.infradead.org
	public-inbox-index barebox

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git