ARM Platforms: Update CNTFRQ register in CNTCTLBase frame
authorSoby Mathew <soby.mathew@arm.com>
Mon, 11 Jun 2018 15:21:30 +0000 (16:21 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Wed, 20 Jun 2018 12:09:30 +0000 (13:09 +0100)
Currently TF-A doesn't initialise CNTFRQ register in CNTCTLBase
frame of the system timer. ARM ARM states that "The instance of
the register in the CNTCTLBase frame must be programmed with this
value as part of system initialization."

The psci_arch_setup() updates the CNTFRQ system register but
according to the ARM ARM, this instance of the register is
independent of the memory mapped instance. This is only an issue
for Normal world software which relies on the memory mapped
instance rather than the system register one.

This patch resolves the issue for ARM platforms.

The patch also solves a related issue on Juno, wherein
CNTBaseN.CNTFRQ can be written and does not reflect the value of
the register in CNTCTLBase frame. Hence this patch additionally
updates CNTFRQ register in the Non Secure frame of the CNTBaseN.

Fixes ARM-Software/tf-issues#593

Change-Id: I09cebb6633688b34d5b1bc349fbde4751025b350
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
include/lib/aarch32/arch.h
include/lib/aarch64/arch.h
include/plat/arm/common/arm_def.h
plat/arm/common/arm_common.c

index 3624cc689219907c68e062100471e53f188108e3..910341a72e9c097bedfcfce94e736bc338cd5bb5 100644 (file)
  * Definitions of register offsets and fields in the CNTCTLBase Frame of the
  * system level implementation of the Generic Timer.
  ******************************************************************************/
+#define CNTCTLBASE_CNTFRQ      U(0x0)
 #define CNTNSAR                        0x4
 #define CNTNSAR_NS_SHIFT(x)    (x)
 
 #define CNTACR_RWVT_SHIFT      0x4
 #define CNTACR_RWPT_SHIFT      0x5
 
+/*******************************************************************************
+ * Definitions of register offsets in the CNTBaseN Frame of the
+ * system level implementation of the Generic Timer.
+ ******************************************************************************/
+#define CNTBASE_CNTFRQ         U(0x10)
+
 /* MAIR macros */
 #define MAIR0_ATTR_SET(attr, index)    ((attr) << ((index) << 3))
 #define MAIR1_ATTR_SET(attr, index)    ((attr) << (((index) - 3) << 3))
index 92bb97d51db3a5e5b16bf0258f19a860a053a8bd..7cc4b23774aae40a4c8ed3681fa7ba117fed0174 100644 (file)
  * Definitions of register offsets and fields in the CNTCTLBase Frame of the
  * system level implementation of the Generic Timer.
  ******************************************************************************/
+#define CNTCTLBASE_CNTFRQ      U(0x0)
 #define CNTNSAR                        U(0x4)
 #define CNTNSAR_NS_SHIFT(x)    (x)
 
 #define CNTACR_RWVT_SHIFT      U(0x4)
 #define CNTACR_RWPT_SHIFT      U(0x5)
 
+/*******************************************************************************
+ * Definitions of register offsets in the CNTBaseN Frame of the
+ * system level implementation of the Generic Timer.
+ ******************************************************************************/
+#define CNTBASE_CNTFRQ         U(0x10)
+
 /* PMCR_EL0 definitions */
 #define PMCR_EL0_RESET_VAL     U(0x0)
 #define PMCR_EL0_N_SHIFT       U(11)
index e07156c00124b0432dccc0c4cb3c0b1d85b33448..e3d0edbce21e01b528c57e94fdcce3fdcee8661f 100644 (file)
 #define ARM_SYS_CNTCTL_BASE            0x2a430000
 #define ARM_SYS_CNTREAD_BASE           0x2a800000
 #define ARM_SYS_TIMCTL_BASE            0x2a810000
+#define ARM_SYS_CNT_BASE_S             0x2a820000
+#define ARM_SYS_CNT_BASE_NS            0x2a830000
 
 #define ARM_CONSOLE_BAUDRATE           115200
 
index 11bdeac66ec415953951694d63c373d5227e48ce..32fd9ee68c95a33bac88cd5d222fb774131dddf3 100644 (file)
@@ -160,6 +160,9 @@ void arm_configure_sys_timer(void)
 {
        unsigned int reg_val;
 
+       /* Read the frequency of the system counter */
+       unsigned int freq_val = plat_get_syscnt_freq2();
+
 #if ARM_CONFIG_CNTACR
        reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
        reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
@@ -169,6 +172,23 @@ void arm_configure_sys_timer(void)
 
        reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
        mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+       /*
+        * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ
+        * system register initialized during psci_arch_setup() is different
+        * from this and has to be updated independently.
+        */
+       mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
+
+#ifdef PLAT_juno
+       /*
+        * Initialize CNTFRQ register in Non-secure CNTBase frame.
+        * This is only required for Juno, because it doesn't follow ARM ARM
+        * in that the value updated in CNTFRQ is not reflected in CNTBASE_CNTFRQ.
+        * Hence update the value manually.
+        */
+       mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASE_CNTFRQ, freq_val);
+#endif
 }
 #endif /* ARM_SYS_TIMCTL_BASE */