armv8/ls2085a: Fix generic timer clock source
Subsystems (2)
PATCH v2 4/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.
---
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(-)
README +8 -0
@@ -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.
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +26 -0
@@ -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 */ + asmvolatile ("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 ; +}
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +6 -0
@@ -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 */
arch/arm/cpu/armv8/fsl-lsch3/mp.h +1 -0
@@ -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 );
board/freescale/ls2085a/ls2085a.c +0 -18
@@ -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. */
include/configs/ls2085a_common.h +5 -1
@@ -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)
Signature · 1 line
1.7.9.5
PATCH v2 4/28 armv8/ls2085a: Fix generic timer clock source
Hi,
Quoted 45 lines · York Sun
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 <[email protected]>---
Changes in v2:
Fix CNTFRQ for secondary cores whenCOUNTER_FREQUENCY_REALis 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(-)README +8
-0@@ -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.arch/arm/cpu/armv8/fsl-lsch3/cpu.c +0
-0@@ -395,3 +395,29 @@ int arch_early_init_r(void)return 0 ; }
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 407
Quoted 10 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +10
-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 */ + asmvolatile ("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.
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 409
Quoted 2 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +2
-0+ + __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?
Quoted 29 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +14
-0+#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 ; +}arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +3
-0@@ -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 */
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S ENDPROC(secondary_switch_to_el1) · line 283
Quoted 6 lines
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +3
-0@@ -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.
PATCH v2 4/28 armv8/ls2085a: Fix generic timer clock source
Quoted 46 lines · Mark Rutland
Hi,
Quoted 43 lines · York Sun
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 <[email protected]>---
Changes in v2:
Fix CNTFRQ for secondary cores whenCOUNTER_FREQUENCY_REALis 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(-)README +8
-0@@ -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.arch/arm/cpu/armv8/fsl-lsch3/cpu.c +0
-0@@ -395,3 +395,29 @@ int arch_early_init_r(void)
Quoted 16 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 407
Quoted 12 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +10
-0return 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 */ + asmvolatile ("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().
Quoted 6 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 409
Quoted 2 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +2
-0+ + __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.
Quoted 31 lines
Quoted 31 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +14
-0+#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 ; +}arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +3
-0@@ -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)
Quoted 8 lines
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S ENDPROC(secondary_switch_to_el1) · line 283
Quoted 5 lines
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +3
-0/* 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
PATCH v2 4/28 armv8/ls2085a: Fix generic timer clock source
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +4
-0+int timer_init (void ) +{ +u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR ; +u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR ;Quoted 9 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 407
Quoted 5 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +5
-0+#ifdef COUNTER_FREQUENCY_REAL +unsigned long cntfrq =COUNTER_FREQUENCY_REAL ; + +/* Update with accurate clock frequency */ + asmvolatile ("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.
Quoted 2 lines
The macro
COUNTER_FREQUENCY_REAis (CONFIG_SYS_CLK_FREQ/4), whereCONFIG_SYS_CLK_FREQis a function callget_board_sys_clk().
Ah, that sounds fine to me then.
Quoted 9 lines
Quoted 5 lines
arch/arm/cpu/armv8/fsl-lsch3/cpu.c int arch_early_init_r(void) · line 409
Quoted 1 line
arch/arm/cpu/armv8/fsl-lsch3/cpu.c +1
-0+ __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.
Quoted 8 lines
Quoted 6 lines
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S ENDPROC(secondary_switch_to_el1) · line 283
Quoted 3 lines
arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +3
-0+ .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.