[RFC PATCH 1/2] clk: sunxi-ng: a64: disable dividers in PLL-CPUX

Maxime Ripard maxime at cerno.tech
Fri Nov 20 10:24:46 EST 2020


On Mon, Nov 09, 2020 at 01:33:57PM +0800, Icenowy Zheng wrote:
> According to the user manual, PLL-CPUX have two dividers, in which P is
> only allowed when the desired rate is less than 240MHz. As the CCU
> framework have no such feature yet and the clock rate that allows P is
> much lower than where we normally operate, disallow the usage of P
> factor now.
> 
> M is not restricted in the user manual, however according to the BSP PLL
> setup table (see [1]), it's not used at all. To follow what the BSP
> does, disable this factor too.
> 
> Disabling the dividers will make it possible to remove the need to
> switch to osc24M when doing frequency scaling on PLL-CPUX.
> 
> In order to prevent boot-time usage of dividers (current known mainline
> U-Boot implementation use m = 2), tweaking of the factors are done when
> probing CCU driver.
> 
> Signed-off-by: Icenowy Zheng <icenowy at aosc.io>
> ---
>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 79 ++++++++++++++++++++++++++-
>  1 file changed, 77 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
> index 5f66bf879772..6108d150a0e3 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
> @@ -4,6 +4,7 @@
>   */
>  
>  #include <linux/clk-provider.h>
> +#include <linux/delay.h>
>  #include <linux/io.h>
>  #include <linux/of_address.h>
>  #include <linux/platform_device.h>
> @@ -23,13 +24,14 @@
>  
>  #include "ccu-sun50i-a64.h"
>  
> +#define SUN50I_A64_PLL_CPUX_REG		0x000
>  static struct ccu_nkmp pll_cpux_clk = {
>  	.enable		= BIT(31),
>  	.lock		= BIT(28),
>  	.n		= _SUNXI_CCU_MULT(8, 5),
>  	.k		= _SUNXI_CCU_MULT(4, 2),
> -	.m		= _SUNXI_CCU_DIV(0, 2),
> -	.p		= _SUNXI_CCU_DIV_MAX(16, 2, 4),
> +	.m		= _SUNXI_CCU_DIV_MAX(16, 2, 1),
> +	.p		= _SUNXI_CCU_DIV_MAX(0, 2, 1),
>  	.common		= {
>  		.reg		= 0x000,
>  		.hw.init	= CLK_HW_INIT("pll-cpux",
> @@ -215,6 +217,7 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
>  				   BIT(28),	/* lock */
>  				   CLK_SET_RATE_UNGATE);
>  
> +#define SUN50I_A64_CPUX_AXI_REG		0x050
>  static const char * const cpux_parents[] = { "osc32k", "osc24M",
>  					     "pll-cpux", "pll-cpux" };
>  static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> @@ -954,6 +957,78 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
>  
>  	writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
>  
> +	/* Disable any possible dividers on PLL-CPUX */
> +	val = readl(reg + SUN50I_A64_PLL_CPUX_REG);
> +	if (val & (GENMASK(17, 16) | GENMASK(1, 0))) {
> +		unsigned int n, k, m, p;
> +
> +		n = ((val & GENMASK(12, 8)) >> 8) + 1;
> +		k = ((val & GENMASK(5, 4)) >> 4) + 1;
> +		m = (val & GENMASK(1, 0)) + 1;
> +		p = 1 << ((val & GENMASK(17, 16)) >> 16);
> +
> +		/*
> +		 * Known mainline U-Boot revisions never uses
> +		 * divider p, and it will only use m when k = 3 or 4.
> +		 * Specially judge for these cases, to satisfy
> +		 * what will most possibly happen.
> +		 * For m = 2 and k = 3, fractional change will be
> +		 * applied to n, to mostly keep the clock rate.
> +		 * For m = 2 and k = 4, just change to m = 1 and k = 2.
> +		 * For other cases, just try to divide it from N.
> +		 */
> +		if (p >= 2) {
> +			n /= p;
> +			p = 1;
> +		}
> +
> +		if (m == 2) {
> +			if (k == 3) {
> +				k = 2;
> +				n = n * 3 / 4;
> +				m = 1;
> +			}
> +			if (k == 4) {
> +				k = 2;
> +				m = 1;
> +			}
> +		}
> +
> +		if (m >= 2) {
> +			n /= m;
> +			m = 1;
> +		}

I'm not sure we should rely on the behavior of U-Boot there, and ideally
we should move that code to a function of its own, but on principle I'm
fine with that code.

Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20201120/9b50f09b/attachment-0001.sig>


More information about the linux-arm-kernel mailing list