armv8/ls2085a: Fix generic timer clock source
authorYork Sun <yorksun@freescale.com>
Sat, 21 Mar 2015 02:28:08 +0000 (19:28 -0700)
committerYork Sun <yorksun@freescale.com>
Thu, 23 Apr 2015 15:55:55 +0000 (08:55 -0700)
The timer clock is system clock divided by 4, not fixed 12MHz.
This is common to the SoC, not board specific. Primary core is
fixed when u-boot still runs in board_f. Secondary cores are
fixed by reading a variable set by u-boot.

Signed-off-by: York Sun <yorksun@freescale.com>
CC: Mark Rutland <mark.rutland@arm.com>
README
arch/arm/cpu/armv8/fsl-lsch3/cpu.c
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
arch/arm/cpu/armv8/fsl-lsch3/mp.c
arch/arm/cpu/armv8/fsl-lsch3/mp.h
board/freescale/ls2085a/ls2085a.c
include/configs/ls2085a_common.h

diff --git a/README b/README
index f5a719d..a70af98 100644 (file)
--- a/README
+++ b/README
@@ -690,6 +690,14 @@ The following options need to be configured:
                exists, unlike the similar options in the Linux kernel. Do not
                set these options unless they apply!
 
+               COUNTER_FREQUENCY
+               Generic timer clock source frequency.
+
+               COUNTER_FREQUENCY_REAL
+               Generic timer clock source frequency if the real clock is
+               different from COUNTER_FREQUENCY, and can only be determined
+               at run time.
+
                NOTE: The following can be machine specific errata. These
                do have ability to provide rudimentary version and machine
                specific checks, but expect no product checks.
index 94fd147..e985181 100644 (file)
@@ -395,3 +395,27 @@ int arch_early_init_r(void)
 
        return 0;
 }
+
+int timer_init(void)
+{
+       u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
+       u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
+#ifdef COUNTER_FREQUENCY_REAL
+       unsigned long cntfrq = COUNTER_FREQUENCY_REAL;
+
+       /* Update with accurate clock frequency */
+       asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
+#endif
+
+       /* Enable timebase for all clusters.
+        * It is safe to do so even some clusters are not enabled.
+        */
+       out_le32(cltbenr, 0xf);
+
+       /* Enable clock for timer
+        * This is a global setting.
+        */
+       out_le32(cntcr, 0x1);
+
+       return 0;
+}
index 886576e..53bdb44 100644 (file)
@@ -224,6 +224,9 @@ ENTRY(secondary_boot_func)
        /* physical address of this cpus spin table element */
        add     x11, x1, x0
 
+       ldr     x0, =__real_cntfrq
+       ldr     x0, [x0]
+       msr     cntfrq_el0, x0  /* set with real frequency */
        str     x9, [x11, #16]  /* LPID */
        mov     x4, #1
        str     x4, [x11, #8]   /* STATUS */
@@ -275,6 +278,9 @@ ENDPROC(secondary_switch_to_el1)
 
        /* 64 bit alignment for elements accessed as data */
        .align 4
+       .global __real_cntfrq
+__real_cntfrq:
+       .quad COUNTER_FREQUENCY
        .globl __secondary_boot_code_size
        .type __secondary_boot_code_size, %object
        /* Secondary Boot Code ends here */
index ce9c0c1..da7853a 100644 (file)
@@ -31,6 +31,13 @@ int fsl_lsch3_wake_seconday_cores(void)
        int i, timeout = 10;
        u64 *table = get_spin_tbl_addr();
 
+#ifdef COUNTER_FREQUENCY_REAL
+       /* update for secondary cores */
+       __real_cntfrq = COUNTER_FREQUENCY_REAL;
+       flush_dcache_range((unsigned long)&__real_cntfrq,
+                          (unsigned long)&__real_cntfrq + 8);
+#endif
+
        cores = cpu_mask();
        /* Clear spin table so that secondary processors
         * observe the correct value after waking up from wfe.
index 66144d6..c985d6a 100644 (file)
@@ -26,6 +26,7 @@
 #define id_to_core(x)  ((x & 3) | (x >> 6))
 #ifndef __ASSEMBLY__
 extern u64 __spin_table[];
+extern u64 __real_cntfrq;
 extern u64 *secondary_boot_code;
 extern size_t __secondary_boot_code_size;
 int fsl_lsch3_wake_seconday_cores(void);
index e78c63a..bd016e9 100644 (file)
@@ -55,24 +55,6 @@ int dram_init(void)
        return 0;
 }
 
-int timer_init(void)
-{
-       u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR;
-       u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
-
-       /* Enable timebase for all clusters.
-        * It is safe to do so even some clusters are not enabled.
-        */
-       out_le32(cltbenr, 0xf);
-
-       /* Enable clock for timer
-        * This is a global setting.
-        */
-       out_le32(cntcr, 0x1);
-
-       return 0;
-}
-
 /*
  * Board specific reset that is system reset.
  */
index 5721b18..f6b3ed0 100644 (file)
 #define CONFIG_DP_DDR_NUM_CTRLS                1
 
 /* Generic Timer Definitions */
-#define COUNTER_FREQUENCY              12000000        /* 12MHz */
+/*
+ * This is not an accurate number. It is used in start.S. The frequency
+ * will be udpated later when get_bus_freq(0) is available.
+ */
+#define COUNTER_FREQUENCY              25000000        /* 25MHz */
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN          (CONFIG_ENV_SIZE + 2048 * 1024)