[PATCH] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present

Sean Anderson seanga2 at gmail.com
Thu Apr 11 04:53:05 CEST 2024


On 3/7/24 19:04, Sam Protsenko 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 at linaro.org>
> ---
>   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);

Can you give an example of where this is needed?

--Sean


More information about the U-Boot mailing list