[PATCH v2 5/5] clk: rockchip: rk3588: fix up the frac pll calculation

Kever Yang kever.yang at rock-chips.com
Fri Oct 13 09:44:08 CEST 2023


On 2023/10/12 18:18, Elaine Zhang wrote:
> rk3588 frac pll:
> FFVCO = ((m + k / 65536) * FFIN) / p
> FFOUT = ((m + k / 65536) * FFIN) / (p * 2s)
> k is the original code, but the K[15:0] is complement code
> (6'b1000_0000_0000_0000 <= K[15:0] <= 16'b0111_1111_1111_1111),
> need to be converted.
>
> Signed-off-by: Elaine Zhang <zhangqing at rock-chips.com>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/clk/rockchip/clk_pll.c | 102 +++++++++++++++++++++++++--------
>   1 file changed, 78 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk_pll.c b/drivers/clk/rockchip/clk_pll.c
> index d657ef38f3c6..1bb31b3313b5 100644
> --- a/drivers/clk/rockchip/clk_pll.c
> +++ b/drivers/clk/rockchip/clk_pll.c
> @@ -168,13 +168,71 @@ rockchip_pll_clk_set_by_auto(ulong fin_hz,
>   	return rate_table;
>   }
>   
> +static u32
> +rockchip_rk3588_pll_k_get(u32 m, u32 p, u32 s, u64 fin_hz, u64 fvco)
> +{
> +	u64 fref, fout, ffrac;
> +	u32 k = 0;
> +
> +	fref = fin_hz / p;
> +	ffrac = fvco - (m * fref);
> +	fout = ffrac * 65536;
> +	k = fout / fref;
> +	if (k > 32767) {
> +		fref = fin_hz / p;
> +		ffrac = ((m + 1) * fref) - fvco;
> +		fout = ffrac * 65536;
> +		k = ((fout * 10 / fref) + 7) / 10;
> +		if (k > 32767)
> +			k = 0;
> +		else
> +			k = ~k + 1;
> +	}
> +	return k;
> +}
> +
> +static struct rockchip_pll_rate_table *
> +rockchip_rk3588_pll_frac_by_auto(unsigned long fin_hz, unsigned long fout_hz)
> +{
> +	struct rockchip_pll_rate_table *rate_table = &rockchip_auto_table;
> +	u32 p, m, s, k;
> +	u64 fvco;
> +
> +	for (s = 0; s <= 6; s++) {
> +		fvco = (u64)fout_hz << s;
> +		if (fvco < RK3588_VCO_MIN_HZ || fvco > RK3588_VCO_MAX_HZ)
> +			continue;
> +		for (p = 1; p <= 4; p++) {
> +			for (m = 64; m <= 1023; m++) {
> +				if ((fvco >= m * fin_hz / p) &&
> +				    (fvco < (m + 1) * fin_hz / p)) {
> +					k = rockchip_rk3588_pll_k_get(m, p, s,
> +								      fin_hz,
> +								      fvco);
> +					if (!k)
> +						continue;
> +					rate_table->p = p;
> +					rate_table->s = s;
> +					rate_table->k = k;
> +					if (k > 32767)
> +						rate_table->m = m + 1;
> +					else
> +						rate_table->m = m;
> +					return rate_table;
> +				}
> +			}
> +		}
> +	}
> +	return NULL;
> +}
> +
>   static struct rockchip_pll_rate_table *
>   rk3588_pll_clk_set_by_auto(unsigned long fin_hz,
>   			   unsigned long fout_hz)
>   {
>   	struct rockchip_pll_rate_table *rate_table = &rockchip_auto_table;
>   	u32 p, m, s;
> -	ulong fvco, fref, fout, ffrac;
> +	ulong fvco;
>   
>   	if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
>   		return NULL;
> @@ -202,27 +260,12 @@ rk3588_pll_clk_set_by_auto(unsigned long fin_hz,
>   		}
>   		pr_err("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz);
>   	} else {
> -		for (s = 0; s <= 6; s++) {
> -			fvco = fout_hz << s;
> -			if (fvco < RK3588_VCO_MIN_HZ ||
> -			    fvco > RK3588_VCO_MAX_HZ)
> -				continue;
> -			for (p = 1; p <= 4; p++) {
> -				for (m = 64; m <= 1023; m++) {
> -					if ((fvco >= m * fin_hz / p) && (fvco < (m + 1) * fin_hz / p)) {
> -						rate_table->p = p;
> -						rate_table->m = m;
> -						rate_table->s = s;
> -						fref = fin_hz / p;
> -						ffrac = fvco - (m * fref);
> -						fout = ffrac * 65536;
> -						rate_table->k = fout / fref;
> -						return rate_table;
> -					}
> -				}
> -			}
> -		}
> -		pr_err("CANNOT FIND Fout by auto,fout = %lu\n", fout_hz);
> +		rate_table = rockchip_rk3588_pll_frac_by_auto(fin_hz, fout_hz);
> +		if (!rate_table)
> +			pr_err("CANNOT FIND Fout by auto,fout = %lu\n",
> +			       fout_hz);
> +		else
> +			return rate_table;
>   	}
>   	return NULL;
>   }
> @@ -533,11 +576,22 @@ static ulong rk3588_pll_get_rate(struct rockchip_pll_clock *pll,
>   
>   		rate = OSC_HZ / p;
>   		rate *= m;
> -		if (k) {
> +		if (k & BIT(15)) {
> +			/* fractional mode */
> +			u64 frac_rate64;
> +
> +			k = (~(k - 1)) & RK3588_PLLCON2_K_MASK;
> +			frac_rate64 = OSC_HZ * k;
> +			postdiv = p;
> +			postdiv *= 65536;
> +			do_div(frac_rate64, postdiv);
> +			rate -= frac_rate64;
> +		} else {
>   			/* fractional mode */
>   			u64 frac_rate64 = OSC_HZ * k;
>   
> -			postdiv = p * 65536;
> +			postdiv = p;
> +			postdiv *= 65536;
>   			do_div(frac_rate64, postdiv);
>   			rate += frac_rate64;
>   		}


More information about the U-Boot mailing list