Linux does boot at 800 MHz LS1020A

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Linux does boot at 800 MHz LS1020A

946 Views
keestrommel
Contributor IV

When setting the PLL configuration of the RCW of our custom LS1020a board for a 800 MHz core clock in the way as recommended in the LS102xa reference manual booting Linux fails. The reason is that QorIQ frequency driver changes the core clock to 1600 MHz.

When using the following configuration RCW PLL configuration Linux boots successfully:

CGA_PLL1_RAT = 00_1000 = 8 (our reference clock frequency is 100 MHz)

C1_PLL_SEL = 0000 = CGA_PLL1 /1

However the reference manual states:

For less than 1 GHz operation:
The value of this field should be twice the required core clock frequency and C1_PLL_SEL should be set to 4’b0001 (CGA_PLL1/2). For example, to achieve 800 MHz core clock frequency with reference clock frequency of 100 MHz, the ratio should be 16 (0x10) for locking the CGA PLL1 at 1600 MHz and C1_PLL_SEL=4’b0001 to achieve 800 MHz core clock frequency

With this PLL RCW configuration booting Linux fails.

My questions are:

  1. What are the disadvantages of using the non recommended PLL RCW settings?
  2. How can the Linux kernel be configured such that it does not select 1600MHz core frequency by overriding the CGA_PLL1/2 setting of the RCW by CGA_PLL1/1?
Labels (1)
0 Kudos
3 Replies

622 Views
keestrommel
Contributor IV

Wang Yiping,

The topology module of the kernel (arch/arm/kernel/topology.c) uses the clock-frequency defined in the FDT. The FDT is generated from the dts file but is modified/updated by the u-boot. However the QorIQ clock driver (drivers/clk/clk-qoriq.c) that cause the problem gets the core clock frequency from the FDT system clock and PLL configuration (PLLC1GSR).

In the mean I got a patch from our NXP FAE that fixed this problem.

The U-Boot has bug. The U-Boot sets the CPU clock frequency in the FDT in local byte order (Little Endian) (ft_cpu_setup in arch/arm/cpu/armv7/ls102xa/fdt.c) while the topology module of the kernel expects it in Big Endian.

As follows the patch file that fixed my problem:

Signed-off-by: Scott Wood <oss@buserror.net>
---
Peter, can you have the customer try this patch?

 drivers/clk/clk-qoriq.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 3d1b6f5..1c0faef 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -709,6 +709,7 @@ static struct clk * __init create_mux_common(struct clockgen *cg,
                          struct mux_hwclock *hwc,
                          const struct clk_ops *ops,
                          unsigned long min_rate,
+                         unsigned long max_rate,
                          unsigned long pct80_rate,
                          const char *fmt, int idx)
 {
@@ -737,6 +738,8 @@ static struct clk * __init create_mux_common(struct clockgen *cg,
             continue;
         if (rate < min_rate)
             continue;
+        if (rate > max_rate)
+            continue;
 
         parent_names[j] = div->name;
         hwc->parent_to_clksel[j] = i;
@@ -768,7 +771,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
     struct mux_hwclock *hwc;
     const struct clockgen_pll_div *div;
     unsigned long plat_rate, min_rate;
-    u64 pct80_rate;
+    u64 max_rate, pct80_rate;
     u32 clksel;
 
     hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
@@ -792,8 +795,8 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
         return NULL;
     }
 
-    pct80_rate = clk_get_rate(div->clk);
-    pct80_rate *= 8;
+    max_rate = clk_get_rate(div->clk);
+    pct80_rate = max_rate * 8;
     do_div(pct80_rate, 10);
 
     plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
@@ -803,7 +806,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
     else
         min_rate = plat_rate / 2;
 
-    return create_mux_common(cg, hwc, &cmux_ops, min_rate,
+    return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate,
                  pct80_rate, "cg-cmux%d", idx);
 }
 
@@ -818,6 +821,6 @@ static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
     hwc->reg = cg->regs + 0x20 * idx + 0x10;
     hwc->info = cg->info.hwaccel[idx];
 
-    return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
+    return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0,
                  "cg-hwaccel%d", idx);
 }

Regards,

Kees.

0 Kudos

622 Views
addiyi
NXP Employee
NXP Employee

Just for reference. 

The driver has no knowledge of what the rated speed of the chip is. It assumes that the PLL is set <= the rated speed and that the dividers are only used to decrease CPU speed. That assumption isn't true if the RCW is configured with a divider (and I do now see that the RM says that's the expected configuration with core frequencies less than 1 GHz).  The driver should be updated to never accept a CPU clock setting greater than what it started with at boot time.

0 Kudos

622 Views
yipingwang
NXP TechSupport
NXP TechSupport

Hello Kees Trommel,

Linux Kernel uses core clock frequency defined in the dts file.

Would you please provide u-boot and failed Linux Kernel log?


Have a great day,
Yiping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos