[U-Boot] [PATCH v2 04/28] armv8/ls2085a: Fix generic timer clock source

The timer clock is system clock divided by 4, not fixed 12MHz. This is common to the SoC, not board specific.
Signed-off-by: York Sun yorksun@freescale.com
---
Changes in v2: Fix CNTFRQ for secondary cores when COUNTER_FREQUENCY_REAL is defined.
README | 8 ++++++++ arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 26 ++++++++++++++++++++++++++ arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S | 6 ++++++ arch/arm/cpu/armv8/fsl-lsch3/mp.h | 1 + board/freescale/ls2085a/ls2085a.c | 18 ------------------ include/configs/ls2085a_common.h | 6 +++++- 6 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/README b/README index f473515..776ebf4 100644 --- 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. diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c index 94fd147..f75b21d 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -395,3 +395,29 @@ 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"); + + __real_cntfrq = cntfrq; /* update for secondary cores */ +#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; +} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S index 886576e..8d330ff 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S @@ -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 0x17d7840 /* 25MHz */ .globl __secondary_boot_code_size .type __secondary_boot_code_size, %object /* Secondary Boot Code ends here */ diff --git a/arch/arm/cpu/armv8/fsl-lsch3/mp.h b/arch/arm/cpu/armv8/fsl-lsch3/mp.h index 66144d6..c985d6a 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/mp.h +++ b/arch/arm/cpu/armv8/fsl-lsch3/mp.h @@ -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); diff --git a/board/freescale/ls2085a/ls2085a.c b/board/freescale/ls2085a/ls2085a.c index e78c63a..bd016e9 100644 --- a/board/freescale/ls2085a/ls2085a.c +++ b/board/freescale/ls2085a/ls2085a.c @@ -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. */ diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h index 339337d..b47cf68 100644 --- a/include/configs/ls2085a_common.h +++ b/include/configs/ls2085a_common.h @@ -72,7 +72,11 @@ #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)

Hi,
On Thu, Mar 19, 2015 at 08:34:22PM +0000, York Sun wrote:
The timer clock is system clock divided by 4, not fixed 12MHz. This is common to the SoC, not board specific.
Signed-off-by: York Sun yorksun@freescale.com
Changes in v2: Fix CNTFRQ for secondary cores when COUNTER_FREQUENCY_REAL is defined.
README | 8 ++++++++ arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 26 ++++++++++++++++++++++++++ arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S | 6 ++++++ arch/arm/cpu/armv8/fsl-lsch3/mp.h | 1 + board/freescale/ls2085a/ls2085a.c | 18 ------------------ include/configs/ls2085a_common.h | 6 +++++- 6 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/README b/README index f473515..776ebf4 100644 --- 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.
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c index 94fd147..f75b21d 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -395,3 +395,29 @@ 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");
The commit message says that this can only be determined at runtime, but this looks like we're writing a compile-time static value.
- __real_cntfrq = cntfrq; /* update for secondary cores */
Do we need anything in the way or barriers and/or cache flushing to ensure that this is visible to the secondary CPUs? Or is the MMU off at this point?
+#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;
+} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S index 886576e..8d330ff 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S @@ -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 0x17d7840 /* 25MHz */
I think this would be better as COUNTER_FREQUENCY, so as to avoid duplicating the value.
Thanks, Mark.

On 03/20/2015 10:34 AM, Mark Rutland wrote:
Hi,
On Thu, Mar 19, 2015 at 08:34:22PM +0000, York Sun wrote:
The timer clock is system clock divided by 4, not fixed 12MHz. This is common to the SoC, not board specific.
Signed-off-by: York Sun yorksun@freescale.com
Changes in v2: Fix CNTFRQ for secondary cores when COUNTER_FREQUENCY_REAL is defined.
README | 8 ++++++++ arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 26 ++++++++++++++++++++++++++ arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S | 6 ++++++ arch/arm/cpu/armv8/fsl-lsch3/mp.h | 1 + board/freescale/ls2085a/ls2085a.c | 18 ------------------ include/configs/ls2085a_common.h | 6 +++++- 6 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/README b/README index f473515..776ebf4 100644 --- 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.
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c index 94fd147..f75b21d 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -395,3 +395,29 @@ 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");
The commit message says that this can only be determined at runtime, but this looks like we're writing a compile-time static value.
The macro COUNTER_FREQUENCY_REA is (CONFIG_SYS_CLK_FREQ/4), where CONFIG_SYS_CLK_FREQ is a function call get_board_sys_clk().
- __real_cntfrq = cntfrq; /* update for secondary cores */
Do we need anything in the way or barriers and/or cache flushing to ensure that this is visible to the secondary CPUs? Or is the MMU off at this point?
It is flushed before booting secondary cores. But I am relying on the trick of enabling cache on flash. It may not be as reliable if someone decide to disable the cache to begin with. I will move the code to somewhere safe in next version.
+#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;
+} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S index 886576e..8d330ff 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S @@ -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 0x17d7840 /* 25MHz */
I think this would be better as COUNTER_FREQUENCY, so as to avoid duplicating the value.
Good idea. Will fix in next version.
York

+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");
The commit message says that this can only be determined at runtime, but this looks like we're writing a compile-time static value.
The macro COUNTER_FREQUENCY_REA is (CONFIG_SYS_CLK_FREQ/4), where CONFIG_SYS_CLK_FREQ is a function call get_board_sys_clk().
Ah, that sounds fine to me then.
- __real_cntfrq = cntfrq; /* update for secondary cores */
Do we need anything in the way or barriers and/or cache flushing to ensure that this is visible to the secondary CPUs? Or is the MMU off at this point?
It is flushed before booting secondary cores. But I am relying on the trick of enabling cache on flash. It may not be as reliable if someone decide to disable the cache to begin with. I will move the code to somewhere safe in next version.
Ok.
- .global __real_cntfrq
+__real_cntfrq:
- .quad 0x17d7840 /* 25MHz */
I think this would be better as COUNTER_FREQUENCY, so as to avoid duplicating the value.
Good idea. Will fix in next version.
Great!
Mark.
participants (2)
-
Mark Rutland
-
York Sun