diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c
index 4191937e5056e4d1683a81de5a0e7d5f1893c9f1..417a5366a409fb786d75efd30ae2f544dbd59405 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_el3();
@@ -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 faca2a10dacc4b6a366a2532379310e2a017012e..793b8958e1ec2868015e9b4044d9656dbb0afd48 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_el3();
@@ -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 2bf57cabefd872d70e1882dd314e50c5b4ed25b0..8c635a905040503e7265b72794aa4e691b1af9ef 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
@@ -291,7 +284,8 @@ 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
 
@@ -299,7 +293,8 @@ 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. 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 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 d44ccb6ec115e77a6abc3fe6570c2ee97868bdbe..a5d9f1d5e91e08dbe9a0aa976e287c34227f53aa 100644
--- a/plat/fvp/aarch64/plat_common.c
+++ b/plat/fvp/aarch64/plat_common.c
@@ -248,3 +248,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 07987e42fe3755d13248e69fb42d3e053a4b220b..9bf83eba10d2db95520f369eaae8efe9d41f10fc 100644
--- a/plat/fvp/bl31_plat_setup.c
+++ b/plat/fvp/bl31_plat_setup.c
@@ -29,9 +29,9 @@
  */
 
 #include <platform.h>
+#include <arch.h>
 #include <fvp_pwrc.h>
 #include <console.h>
-#include <bl_common.h>
 
 /*******************************************************************************
  * Declarations of linker defined symbols which will help us find the layout
@@ -141,6 +141,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);