All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yixun Lan <dlan@kernel.org>
To: Dave Klotz <DaveWK225@protonmail.com>
Cc: u-boot@lists.u-boot-project.org, Lukasz Majewski <lukma@denx.de>,
	Tom Rini <trini@konsulko.com>,
	Junhui Liu <junhui.liu@pigmoral.tech>
Subject: Re: [PATCH] clk: spacemit: program the mux when setting a mix clock's rate
Date: Sat, 3 Oct 2026 01:04:52 +0000	[thread overview]
Message-ID: <20261003010452-GKG51329@kernel.org> (raw)
In-Reply-To: <5aa2337bcb969568749c4728354164d5a6c88f27.1790975596.git.DaveWK225@protonmail.com>

hi Dave,

On 21:29 Fri 02 Oct     , Dave Klotz wrote:
> ccu_mix_set_rate() picks the best parent and divider but writes only
> the divider. U-Boot's CCF has no determine_rate step that would reparent
> the clock first, so the clock keeps running from whatever source the
> mux selects, at a rate the caller never asked for. Worse, when the
> hardware mux selects a source that this build's parent list does not
> contain (the K1 SPL lists only pll1_d6_409p6 for the SDH clocks), init
> registers the clock under parents[0] and the clock framework's idea of
> the parent no longer matches the hardware.
> 
> Write the chosen parent's mux index and the divider together and latch
> both with one frequency change. Enable the new parent first and reparent
> the clock device after, so the framework follows the hardware. Nothing
> is written when the mux and divider already match, so a clock left
> running at the requested rate by an earlier stage is not disturbed.
> 
> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com>
> ---
> Tested on an OrangePi R2S booting from eMMC, where the SDH2 io clock
> moves from the BootROM's 409.6 MHz to 204.8 MHz in the SPL, together
> with "clk: spacemit: ccu_mix: fix inverted condition in
> ccu_mix_trigger_fc()" from the K3 clock series, and on an OrangePi RV2
> booting from microSD.
> 
>  drivers/clk/spacemit/clk_mix.c | 54 +++++++++++++++++++++++++++++-----
>  1 file changed, 46 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/clk/spacemit/clk_mix.c b/drivers/clk/spacemit/clk_mix.c
> index a1158512a9..3521ab9374 100644
> --- a/drivers/clk/spacemit/clk_mix.c
> +++ b/drivers/clk/spacemit/clk_mix.c
> @@ -9,6 +9,7 @@
>   */
>  
>  #include <dm/device.h>
> +#include <dm/device-internal.h>
>  #include <dm/uclass.h>
>  #include <div64.h>
>  #include <regmap.h>
> @@ -136,26 +137,63 @@ ccu_mix_calc_best_rate(struct clk *clk, unsigned long rate,
>  	return best_rate;
>  }
>  
> +/*
> + * U-Boot's CCF has no determine_rate, so the parent is chosen here along with
> + * the divider. The mux is programmed from the chosen parent rather than left
> + * where it was found: init falls back to parents[0] when the hardware mux
> + * selects a source this build does not list (the SPL lists only a subset), and
> + * the clock would otherwise keep running from that source at a rate nobody
> + * computed. Mux and divider are written together and latched by one frequency
> + * change, and nothing is written when both already match, so a clock left
> + * running by an earlier stage is not disturbed.
> + */
>  static unsigned long ccu_mix_set_rate(struct clk *clk, unsigned long rate)
>  {
>  	struct ccu_mix *mix = clk_to_ccu_mix(clk);
>  	struct ccu_common *common = &mix->common;
>  	struct ccu_div_config *div = &mix->div;
> -	u32 current_div, target_div, mask;
> +	struct ccu_mux_config *mux = &mix->mux;
> +	struct clk *parent = NULL;
> +	unsigned long parent_rate;
> +	u32 target_div = 0, mask, val;
> +	int i, ret;
>  
> -	ccu_mix_calc_best_rate(clk, rate, NULL, NULL, &target_div);
> +	ccu_mix_calc_best_rate(clk, rate, &parent, &parent_rate, &target_div);
>  
> -	current_div = ccu_read(common, ctrl) >> div->shift;
> -	current_div &= (1 << div->width) - 1;
> +	mask = GENMASK(div->width + div->shift - 1, div->shift);
> +	val = target_div << div->shift;
> +
> +	if (mux->width && parent) {
> +		for (i = 0; i < common->num_parents; i++)
> +			if (!strcmp(parent->dev->name, common->parents[i]))
> +				break;
> +		if (i == common->num_parents)
> +			return -EINVAL;
> +		mask |= GENMASK(mux->width + mux->shift - 1, mux->shift);
> +		val |= i << mux->shift;
> +	} else {
> +		parent = NULL;
> +	}
>  
> -	if (current_div == target_div)
> +	if ((ccu_read(common, ctrl) & mask) == val)
>  		return 0;
>  
> -	mask = GENMASK(div->width + div->shift - 1, div->shift);
> +	if (parent && clk->dev->parent != parent->dev) {
> +		ret = clk_enable(parent);
> +		if (ret)
> +			return ret;
> +	}
>  
.. this will enable parent, would be it ok to combine below
device_reparent() together? to simply use clk_set_parent(clk,
parent)? it make sense to me to reparent first then program
the divider

> -	ccu_update(common, ctrl, mask, target_div << div->shift);
> +	ccu_update(common, ctrl, mask, val);
>  
> -	return ccu_mix_trigger_fc(clk);
> +	ret = ccu_mix_trigger_fc(clk);
> +	if (ret)
> +		return ret;
> +
..
> +	if (parent && clk->dev->parent != parent->dev)
> +		return device_reparent(clk->dev, parent->dev);
> +
reparent clk
> +	return 0;
>  }
>  

-- 
Yixun Lan (dlan)

  parent reply	other threads:[~2026-10-03  1:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-02 21:29 [PATCH] clk: spacemit: program the mux when setting a mix clock's rate Dave Klotz
2026-10-02 22:05 ` Dave Klotz
2026-10-03  1:04 ` Yixun Lan [this message]
2026-10-03  2:29   ` Dave Klotz
2026-10-03  2:39 ` [PATCH v2] " Dave Klotz
2026-10-04  2:18   ` Yixun Lan
2026-10-05 17:35     ` Dave Klotz
2026-10-05 17:40     ` [PATCH v3] " Dave Klotz
2026-10-09  7:26       ` Yixun Lan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261003010452-GKG51329@kernel.org \
    --to=dlan@kernel.org \
    --cc=DaveWK225@protonmail.com \
    --cc=junhui.liu@pigmoral.tech \
    --cc=lukma@denx.de \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.u-boot-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.