
On Thu, Mar 7, 2024 at 6:04 PM Sam Protsenko semen.protsenko@linaro.org wrote:
Sometimes clocks provided to a consumer might not have .set_rate operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag set. In that case it's usually possible to find a parent up the tree which is capable of setting the rate (div, pll, etc). Implement a simple lookup procedure for such cases, to traverse the clock tree until .set_rate capable parent is found, and use that parent to actually change the rate. The search will stop once the first .set_rate capable clock is found, which is usually enough to handle most cases.
Signed-off-by: Sam Protsenko semen.protsenko@linaro.org
Hi Lukasz, Sean, Tom,
If this patch looks good to you and there are no outstanding comments, can you please apply it? It's needed as a part of eMMC enablement for E850-96 board, as eMMC gate (leaf) clock is specified as ciu clock in dts, which requires further clock rate change propagation up to divider clock.
Thanks!
drivers/clk/clk-uclass.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index ed6e60bc4841..755f05f34669 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -571,8 +571,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) return 0; ops = clk_dev_ops(clk->dev);
if (!ops->set_rate)
return -ENOSYS;
/* Try to find parents which can set rate */
while (!ops->set_rate) {
struct clk *parent;
if (!(clk->flags & CLK_SET_RATE_PARENT))
return -ENOSYS;
parent = clk_get_parent(clk);
if (IS_ERR_OR_NULL(parent) || !clk_valid(parent))
return -ENODEV;
clk = parent;
ops = clk_dev_ops(clk->dev);
} /* get private clock struct used for cache */ clk_get_priv(clk, &clkp);
-- 2.39.2