Merge pull request #38 from sandrine-bailleux/sb/tf-issue-125
Fix system counter initialisation
diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c
index f9443aa..417a536 100644
--- a/bl1/aarch64/bl1_arch_setup.c
+++ b/bl1/aarch64/bl1_arch_setup.c
@@ -59,8 +59,6 @@
*/
enable_serror();
enable_debug_exceptions();
-
- return;
}
/*******************************************************************************
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c
index 2a424f8..793b895 100644
--- a/bl31/aarch64/bl31_arch_setup.c
+++ b/bl31/aarch64/bl31_arch_setup.c
@@ -40,6 +40,7 @@
void bl31_arch_setup(void)
{
unsigned long tmp_reg = 0;
+ uint64_t counter_freq;
/* Enable alignment checks and set the exception endianness to LE */
tmp_reg = read_sctlr_el3();
@@ -61,7 +62,9 @@
enable_serror();
enable_debug_exceptions();
- return;
+ /* Program the counter frequency */
+ counter_freq = plat_get_syscnt_freq();
+ write_cntfrq_el0(counter_freq);
}
/*******************************************************************************
diff --git a/docs/firmware-design.md b/docs/firmware-design.md
index e92042d..8c635a9 100644
--- a/docs/firmware-design.md
+++ b/docs/firmware-design.md
@@ -153,14 +153,10 @@
#### Platform initialization
-BL1 enables issuing of snoop and DVM (Distributed Virtual Memory) requests
-from the CCI-400 slave interface corresponding to the cluster that includes
-the primary CPU. BL1 also initializes UART0 (PL011 console), which enables
-access to the `printf` family of functions in BL1. The `CNTFRQ_EL0` register is
-programmed with the base frequency of the system counter, which is retrieved
-from the first entry in the frequency modes table. The system level
-implementation of the generic timer is enabled through the memory mapped
-interface.
+BL1 enables issuing of snoop and DVM (Distributed Virtual Memory) requests from
+the CCI-400 slave interface corresponding to the cluster that includes the
+primary CPU. BL1 also initializes UART0 (PL011 console), which enables access to
+the `printf` family of functions in BL1.
#### BL2 image load and execution
@@ -288,7 +284,8 @@
since this is the only mechanism to access the runtime services implemented by
BL3-1 (PSCI for example). BL3-1 checks each SMC for validity as specified by
the [SMC calling convention PDD][SMCCC] before passing control to the required
-SMC handler routine.
+SMC handler routine. BL3-1 programs the `CNTFRQ_EL0` register with the clock
+frequency of the system counter, which is provided by the platform.
#### Platform initialization
@@ -296,7 +293,8 @@
software to function correctly. It also retrieves entrypoint information for
the BL3-3 image loaded by BL2 from the platform defined memory address populated
by BL2. BL3-1 also initializes UART0 (PL011 console), which enables
-access to the `printf` family of functions in BL3-1
+access to the `printf` family of functions in BL3-1. It enables the system
+level implementation of the generic timer through the memory mapped interface.
* GICv2 initialization:
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 6bba360..5dca6fd 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -208,6 +208,13 @@
platform) & `platform_get_stack()` (to return the base address of that
stack) (see [../plat/common/aarch64/platform_helpers.S]).
+* **Function : uint64_t plat_get_syscnt_freq(void)**
+
+ This function is used by the architecture setup code to retrieve the
+ counter frequency for the CPU's generic timer. This value will be
+ programmed into the `CNTFRQ_EL0` register.
+ In the ARM FVP port, it returns the base frequency of the system counter,
+ which is retrieved from the first entry in the frequency modes table.
2.2 Common optional modifications
---------------------------------
@@ -446,10 +453,6 @@
for performing any remaining platform-specific setup that can occur after the
MMU and data cache have been enabled.
-In the ARM FVP port, this function enables system-level implementation of the
-generic timer counter. It also initializes counter frequency for CPU's generic
-timers.
-
This function is also responsible for initializing the storage abstraction layer
which is used to load further bootloader images.
@@ -772,7 +775,7 @@
The ARM FVP port does the following:
* Initializes the generic interrupt controller.
* Configures the CLCD controller.
-* Initializes counter frequency for CPU's generic timer
+* Enables system-level implementation of the generic timer counter.
* Grants access to the system counter timer module
* Initializes the FVP power controller device
* Detects the system topology.
diff --git a/include/aarch64/arch.h b/include/aarch64/arch.h
index 3e67282..a41e82b 100644
--- a/include/aarch64/arch.h
+++ b/include/aarch64/arch.h
@@ -78,7 +78,7 @@
#define CNTCR_EN (1 << 0)
#define CNTCR_HDBG (1 << 1)
-#define CNTCR_FCREQ(x) (1 << (8 + (x)))
+#define CNTCR_FCREQ(x) ((x) << 8)
/*******************************************************************************
* System register bit definitions
diff --git a/plat/fvp/aarch64/plat_common.c b/plat/fvp/aarch64/plat_common.c
index d44ccb6..a5d9f1d 100644
--- a/plat/fvp/aarch64/plat_common.c
+++ b/plat/fvp/aarch64/plat_common.c
@@ -248,3 +248,16 @@
{
return NS_IMAGE_OFFSET;
}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+ uint64_t counter_base_frequency;
+
+ /* Read the frequency from Frequency modes table */
+ counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ assert(counter_base_frequency != 0);
+
+ return counter_base_frequency;
+}
diff --git a/plat/fvp/bl1_plat_setup.c b/plat/fvp/bl1_plat_setup.c
index b0c011e..67694f4 100644
--- a/plat/fvp/bl1_plat_setup.c
+++ b/plat/fvp/bl1_plat_setup.c
@@ -112,25 +112,8 @@
******************************************************************************/
void bl1_platform_setup(void)
{
- unsigned int counter_base_frequency;
-
/* Initialise the IO layer and register platform IO devices */
io_setup();
-
- /*
- * Enable and initialize the System level generic timer. Choose base
- * frequency for the timer
- */
- mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
-
- /* Read the frequency from Frequency modes table */
- counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
-
- /* The first entry of the frequency modes table must not be 0 */
- assert(counter_base_frequency != 0);
-
- /* Program the counter frequency */
- write_cntfrq_el0(counter_base_frequency);
}
diff --git a/plat/fvp/bl31_plat_setup.c b/plat/fvp/bl31_plat_setup.c
index eb137e0..9bf83eb 100644
--- a/plat/fvp/bl31_plat_setup.c
+++ b/plat/fvp/bl31_plat_setup.c
@@ -29,9 +29,8 @@
*/
#include <platform.h>
+#include <arch.h>
#include <fvp_pwrc.h>
-#include <assert.h>
-#include <arch_helpers.h>
#include <console.h>
/*******************************************************************************
@@ -129,7 +128,6 @@
void bl31_platform_setup()
{
unsigned int reg_val;
- unsigned int counter_base_frequency;
/* Initialize the gic cpu and distributor interfaces */
gic_setup();
@@ -143,14 +141,8 @@
mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
(1ull << 31) | (1 << 30) | (7 << 20) | (0 << 16));
- /* Read the frequency from Frequency modes table */
- counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
-
- /* The first entry of the frequency modes table must not be 0 */
- assert(counter_base_frequency != 0);
-
- /* Program the counter frequency */
- write_cntfrq_el0(counter_base_frequency);
+ /* Enable and initialize the System level generic timer */
+ mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
/* Allow access to the System counter timer module */
reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
diff --git a/plat/fvp/platform.h b/plat/fvp/platform.h
index 53f14aa..5f4adc3 100644
--- a/plat/fvp/platform.h
+++ b/plat/fvp/platform.h
@@ -346,6 +346,7 @@
extern void plat_report_exception(unsigned long);
extern unsigned long plat_get_ns_image_entrypoint(void);
extern unsigned long platform_get_stack(unsigned long mpidr);
+extern uint64_t plat_get_syscnt_freq(void);
/* Declarations for fvp_gic.c */
extern void gic_cpuif_deactivate(unsigned int);