diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c index 3a528e1dd12853c02ff5a42f5f51cf95c1f5724b..3e84b89ecedb6eca1d8f107a69479ebede6a314d 100644 --- a/bl1/aarch64/bl1_arch_setup.c +++ b/bl1/aarch64/bl1_arch_setup.c @@ -39,7 +39,6 @@ void bl1_arch_setup(void) { unsigned long tmp_reg = 0; - unsigned int counter_base_frequency; /* Enable alignment checks and set the exception endianess to LE */ tmp_reg = read_sctlr(); @@ -60,15 +59,6 @@ void bl1_arch_setup(void) */ enable_serror(); enable_debug_exceptions(); - - /* 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); - return; } /******************************************************************************* diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c index 03b9623c02c2ccfe8039226d577f97b845c873e2..29970fac621868cac5a91f90d70bc60aedd641d5 100644 --- a/bl31/aarch64/bl31_arch_setup.c +++ b/bl31/aarch64/bl31_arch_setup.c @@ -40,7 +40,7 @@ void bl31_arch_setup(void) { unsigned long tmp_reg = 0; - unsigned int counter_base_frequency; + uint64_t counter_freq; /* Enable alignment checks and set the exception endianness to LE */ tmp_reg = read_sctlr(); @@ -62,14 +62,9 @@ void bl31_arch_setup(void) enable_serror(); enable_debug_exceptions(); - /* 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); - return; + counter_freq = plat_get_syscnt_freq(); + write_cntfrq_el0(counter_freq); } /******************************************************************************* diff --git a/docs/firmware-design.md b/docs/firmware-design.md index 11d6f1d05a222fbeade87a94ba5a1d787487ee29..c8bcbb44ba62cedaa03848f73a4e1ec7b00f0812 100644 --- a/docs/firmware-design.md +++ b/docs/firmware-design.md @@ -151,13 +151,6 @@ BL1 performs minimal architectural initialization as follows. and Advanced SIMD execution are configured to not trap to EL3 by clearing the `CPTR_EL3.TFP` bit. - - `CNTFRQ_EL0`. 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. - - - Generic Timer. The system level implementation of the generic timer is - enabled through the memory mapped interface. - #### Platform initialization BL1 enables issuing of snoop and DVM (Distributed Virtual Memory) requests from @@ -289,14 +282,16 @@ exception is raised. They implement more elaborate support for handling SMCs 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 BL3-1 performs detailed platform initialization, which enables normal world 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. +by BL2. 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 56467fb97bd62117698e0a9a7b37bb7915a652fc..5dca6fd5821c2a1470d983a6a650f2ba2c46daa2 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -208,6 +208,13 @@ the implementer chooses. In the ARM FVP port, they are implemented in 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,9 +453,6 @@ This function executes with the MMU and data caches enabled. It is responsible for performing any remaining platform-specific setup that can occur after the MMU and data cache have been enabled. -In the ARM FVP port, it zeros out the ZI section and enables the system level -implementation of the generic timer counter. - This function is also responsible for initializing the storage abstraction layer which is used to load further bootloader images. @@ -771,6 +775,7 @@ BL3-1 runtime services and normal world software can function correctly. The ARM FVP port does the following: * Initializes the generic interrupt controller. * Configures the CLCD controller. +* 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 3e67282c86c768ea5c862e9eb604ca281c7b92e7..a41e82b6479f0bcf737654136e1df991c630b1a5 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 9dbcb8ff9d4828c1828fa885681d4d855fa90f78..172c4b32e5dc75d0d7c154907eb03bb2f75ee6df 100644 --- a/plat/fvp/aarch64/plat_common.c +++ b/plat/fvp/aarch64/plat_common.c @@ -230,3 +230,16 @@ unsigned long plat_get_ns_image_entrypoint(void) { 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 d4fd81b2524c28a70e745ca7433e033297b9c09d..67694f422f4415b1b92b6fbadf46c2b8099a1a18 100644 --- a/plat/fvp/bl1_plat_setup.c +++ b/plat/fvp/bl1_plat_setup.c @@ -114,9 +114,6 @@ void bl1_platform_setup(void) { /* Initialise the IO layer and register platform IO devices */ io_setup(); - - /* Enable and initialize the System level generic timer */ - mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_EN); } diff --git a/plat/fvp/bl31_plat_setup.c b/plat/fvp/bl31_plat_setup.c index 01b0a454c6c10c424dd5f63c025174ac44e6098e..ee3899daa7f4baf5bc80bec97d55ac7427aebbd7 100644 --- a/plat/fvp/bl31_plat_setup.c +++ b/plat/fvp/bl31_plat_setup.c @@ -29,6 +29,7 @@ */ #include <platform.h> +#include <arch.h> #include <fvp_pwrc.h> #include <bl_common.h> @@ -138,6 +139,9 @@ void bl31_platform_setup() mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, (1ull << 31) | (1 << 30) | (7 << 20) | (0 << 16)); + /* 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); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); diff --git a/plat/fvp/platform.h b/plat/fvp/platform.h index 53f14aa405f884143f634f7c385f14753a6bf9f8..5f4adc39787c6331890ad31f74ac9c74ff305765 100644 --- a/plat/fvp/platform.h +++ b/plat/fvp/platform.h @@ -346,6 +346,7 @@ extern int platform_config_setup(void); 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);