Fix SP804 delay timer on FVP
authorJuan Castillo <juan.castillo@arm.com>
Tue, 1 Dec 2015 16:10:15 +0000 (16:10 +0000)
committerJuan Castillo <juan.castillo@arm.com>
Fri, 4 Dec 2015 10:23:33 +0000 (10:23 +0000)
This patch fixes several issues with the SP804 delay timer on FVP:

* By default, the SP804 dual timer on FVP runs at 32 KHz. In order
  to run the timer at 35 MHz (as specified in the FVP user manual)
  the Overwrite bit in the SP810 control register must be set.

* The CLKMULT and CLKDIV definitions are mixed up:

      delta(us) = delta(ticks) * T(us) = delta(ticks) / f(MHz)

  From the delay function:

      delta_us = (delta * ops->clk_mult) / ops->clk_div;

  Matching both expressions:

      1 / f(MHz) = ops->clk_mult / ops->clk_div

  And consequently:

      f(MHz) = ops->clk_div / ops->clk_mult

  Which, for a 35 MHz timer, translates to:

      ops->clk_div = 35
      ops->clk_mult = 1

* The comment in the delay timer header file has been corrected:
  The ratio of the multiplier and the divider is the clock period
  in microseconds, not the frequency.

Change-Id: Iffd5ce0a5a28fa47c0720c0336d81b678ff8fdf1

include/drivers/delay_timer.h
include/plat/arm/board/common/v2m_def.h
plat/arm/board/fvp/fvp_bl2_setup.c
plat/arm/board/fvp/fvp_def.h

index 4f3bdc88abf4204a6b973afac32d87de9319bc70..0dec626c8d5d05fe3e416ab25273781f31d7eb68 100644 (file)
@@ -38,7 +38,7 @@
  * The driver must be initialized with a structure that provides a
  * function pointer to return the timer value and a clock
  * multiplier/divider. The ratio of the multiplier and the divider is
- * the clock frequency in MHz.
+ * the clock period in microseconds.
  ********************************************************************/
 
 typedef struct timer_ops {
index 7ed0af6c4a92c3a5cc62a3c87ac1e870d1785364..888792edd2d47b934bb19f0d47a21726be6b00f0 100644 (file)
 #define V2M_SP804_TIMER0_BASE          0x1C110000
 #define V2M_SP804_TIMER1_BASE          0x1C120000
 
+/* SP810 controller */
+#define V2M_SP810_BASE                 0x1c020000
+#define V2M_SP810_CTRL_TIM0_SEL                (1 << 15)
+#define V2M_SP810_CTRL_TIM1_SEL                (1 << 17)
+#define V2M_SP810_CTRL_TIM2_SEL                (1 << 19)
+#define V2M_SP810_CTRL_TIM3_SEL                (1 << 21)
+
 #define V2M_MAP_FLASH0_RW              MAP_REGION_FLAT(V2M_FLASH0_BASE,\
                                                V2M_FLASH0_SIZE,        \
                                                MT_DEVICE | MT_RW | MT_SECURE)
index b1cdef487ebfafee2f482899da4b545426a605cd..305309ab0a0171144ed44a3458b420bdfc2031fb 100644 (file)
@@ -28,6 +28,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <mmio.h>
 #include <plat_arm.h>
 #include <sp804_delay_timer.h>
 #include <v2m_def.h>
@@ -47,6 +48,10 @@ void bl2_platform_setup(void)
 {
        arm_bl2_platform_setup();
 
+       /* Enable the clock override for SP804 timer 0, which means that no
+        * clock dividers are applied and the raw (35 MHz) clock will be used */
+       mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
+
        /* Initialize delay timer driver using SP804 dual timer 0 */
        sp804_timer_init(V2M_SP804_TIMER0_BASE,
                        SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
index 3af4db68d5cf666b7f6596f83767fa128857241b..41b872af5988a16f575968be02a911aadd312a49 100644 (file)
 #define PWRC_BASE                      0x1c100000
 
 /* FVP SP804 timer frequency is 35 MHz*/
-#define SP804_TIMER_CLKMULT            35
-#define SP804_TIMER_CLKDIV             1
+#define SP804_TIMER_CLKMULT            1
+#define SP804_TIMER_CLKDIV             35
+
+/* SP810 controller. FVP specific flags */
+#define FVP_SP810_CTRL_TIM0_OV         (1 << 16)
+#define FVP_SP810_CTRL_TIM1_OV         (1 << 18)
+#define FVP_SP810_CTRL_TIM2_OV         (1 << 20)
+#define FVP_SP810_CTRL_TIM3_OV         (1 << 22)
 
 /*******************************************************************************
  * GIC-400 & interrupt handling related constants