From 0df8d7f20d1e1e0cddf52f3338989f4fdf2cd8ad Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 10 Feb 2014 12:21:24 +0100 Subject: bsps/arm: Use Global Timer for Cortex-A9 MPCore Use the Global Timer for the Cortex-A9 MPCore clock driver instead of the Private Timer. This enables a consistent nanoseconds since last context switch value across all processors. --- c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h | 2 + .../libbsp/arm/shared/arm-a9mpcore-clock-config.c | 76 +++++++++++++++------- .../libbsp/arm/shared/include/arm-a9mpcore-regs.h | 16 +++-- .../libbsp/arm/shared/include/arm-a9mpcore-start.h | 11 ++++ c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h | 2 + 5 files changed, 78 insertions(+), 29 deletions(-) diff --git a/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h b/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h index c4f14d46ee..959ff92e8f 100644 --- a/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h +++ b/c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h @@ -45,6 +45,8 @@ extern "C" { #define BSP_ARM_GIC_CPUIF_BASE 0x1f000100 +#define BSP_ARM_A9MPCORE_GT_BASE 0x1f000200 + #define BSP_ARM_A9MPCORE_PT_BASE 0x1f000600 #define BSP_ARM_GIC_DIST_BASE 0x1f001000 diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c index de8a1933e0..6f9990cf1d 100644 --- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c +++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -17,7 +17,7 @@ #include #include -#define A9MPCORE_PT ((volatile a9mpcore_pt *) BSP_ARM_A9MPCORE_PT_BASE) +#define A9MPCORE_GT ((volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE) static uint64_t a9mpcore_clock_last_tick_k; @@ -32,9 +32,9 @@ __attribute__ ((weak)) uint32_t a9mpcore_clock_periphclk(void) static void a9mpcore_clock_at_tick(void) { - volatile a9mpcore_pt *pt = A9MPCORE_PT; + volatile a9mpcore_gt *gt = A9MPCORE_GT; - pt->irqst = A9MPCORE_PT_IRQST_EFLG; + gt->irqst = A9MPCORE_GT_IRQST_EFLG; } static void a9mpcore_clock_handler_install(void) @@ -42,7 +42,7 @@ static void a9mpcore_clock_handler_install(void) rtems_status_code sc; sc = rtems_interrupt_handler_install( - A9MPCORE_IRQ_PT, + A9MPCORE_IRQ_GT, "Clock", RTEMS_INTERRUPT_UNIQUE, (rtems_interrupt_handler) Clock_isr, @@ -56,31 +56,56 @@ static void a9mpcore_clock_handler_install(void) } } -static void a9mpcore_clock_initialize(void) +static uint64_t a9mpcore_clock_get_counter(volatile a9mpcore_gt *gt) { - volatile a9mpcore_pt *pt = A9MPCORE_PT; - uint64_t periphclk = (uint64_t) a9mpcore_clock_periphclk(); - uint64_t interval = (periphclk - * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; + uint32_t cl; + uint32_t cu1; + uint32_t cu2; + + do { + cu1 = gt->cntrupper; + cl = gt->cntrlower; + cu2 = gt->cntrupper; + } while (cu1 != cu2); - a9mpcore_clock_last_tick_k = (1000000000ULL << 32) / periphclk; + return ((uint64_t) cu2 << 32) | cl; +} - pt->load = (uint32_t) interval - 1; - pt->ctrl = A9MPCORE_PT_CTRL_AUTO_RLD - | A9MPCORE_PT_CTRL_IRQ_EN - | A9MPCORE_PT_CTRL_TMR_EN; +static void a9mpcore_clock_initialize(void) +{ + volatile a9mpcore_gt *gt = A9MPCORE_GT; + uint64_t periphclk = a9mpcore_clock_periphclk(); + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint32_t interval = (uint32_t) ((periphclk * us_per_tick) / 1000000); + uint64_t cmpval; + + a9mpcore_clock_last_tick_k = (UINT64_C(1000000000) << 32) / periphclk; + + gt->ctrl &= A9MPCORE_GT_CTRL_TMR_EN; + gt->irqst = A9MPCORE_GT_IRQST_EFLG; + + cmpval = a9mpcore_clock_get_counter(gt); + cmpval += interval; + + gt->cmpvallower = (uint32_t) cmpval; + gt->cmpvalupper = (uint32_t) (cmpval >> 32); + gt->autoinc = interval; + gt->ctrl = A9MPCORE_GT_CTRL_AUTOINC_EN + | A9MPCORE_GT_CTRL_IRQ_EN + | A9MPCORE_GT_CTRL_COMP_EN + | A9MPCORE_GT_CTRL_TMR_EN; } static void a9mpcore_clock_cleanup(void) { - volatile a9mpcore_pt *pt = A9MPCORE_PT; + volatile a9mpcore_gt *gt = A9MPCORE_GT; rtems_status_code sc; - pt->ctrl = 0; - pt->irqst = A9MPCORE_PT_IRQST_EFLG; + gt->ctrl &= A9MPCORE_GT_CTRL_TMR_EN; + gt->irqst = A9MPCORE_GT_IRQST_EFLG; sc = rtems_interrupt_handler_remove( - A9MPCORE_IRQ_PT, + A9MPCORE_IRQ_GT, (rtems_interrupt_handler) Clock_isr, NULL ); @@ -94,16 +119,17 @@ static void a9mpcore_clock_cleanup(void) static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void) { - volatile a9mpcore_pt *pt = A9MPCORE_PT; + volatile a9mpcore_gt *gt = A9MPCORE_GT; uint64_t k = a9mpcore_clock_last_tick_k; - uint32_t c = pt->cntr; - uint32_t p = pt->load + 1; + uint32_t c = gt->cntrlower; + uint32_t n = gt->cmpvallower; + uint32_t i = gt->autoinc; - if ((pt->irqst & A9MPCORE_PT_IRQST_EFLG) != 0) { - c = pt->cntr - p; + if ((gt->irqst & A9MPCORE_GT_IRQST_EFLG) != 0) { + n = gt->cmpvallower - i; } - return (uint32_t) (((p - c) * k) >> 32); + return (uint32_t) (((c - n - i) * k) >> 32); } #define Clock_driver_support_at_tick() \ diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h index 86bdcb2d20..0910e4c5b2 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h @@ -58,12 +58,20 @@ typedef struct { } a9mpcore_gic; typedef struct { - uint32_t cntr; - uint32_t reserved_04; + uint32_t cntrlower; + uint32_t cntrupper; +#define A9MPCORE_GT_CTRL_PRESCALER(val) BSP_FLD32(val, 8, 15) +#define A9MPCORE_GT_CTRL_PRESCALER_GET(reg) BSP_FLD32GET(reg, 8, 15) +#define A9MPCORE_GT_CTRL_PRESCALER_SET(reg, val) BSP_FLD32SET(reg, val, 8, 15) +#define A9MPCORE_GT_CTRL_AUTOINC_EN BSP_BIT32(3) +#define A9MPCORE_GT_CTRL_IRQ_EN BSP_BIT32(2) +#define A9MPCORE_GT_CTRL_COMP_EN BSP_BIT32(1) +#define A9MPCORE_GT_CTRL_TMR_EN BSP_BIT32(0) uint32_t ctrl; +#define A9MPCORE_GT_IRQST_EFLG BSP_BIT32(0) uint32_t irqst; - uint32_t cmpval; - uint32_t reserved_14; + uint32_t cmpvallower; + uint32_t cmpvalupper; uint32_t autoinc; } a9mpcore_gt; diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h index a62dcdaf83..9ebc5a5cac 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h @@ -120,8 +120,19 @@ BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_hook_0(void) #endif } +BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_global_timer(void) +{ + volatile a9mpcore_gt *gt = (volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE; + + gt->ctrl = 0; + gt->cntrlower = 0; + gt->cntrupper = 0; + gt->ctrl = A9MPCORE_GT_CTRL_TMR_EN; +} + BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_hook_1(void) { + arm_a9mpcore_start_global_timer(); arm_a9mpcore_start_set_vector_base(); } diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h b/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h index c722d189f9..56e62a5633 100644 --- a/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h +++ b/c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h @@ -49,6 +49,8 @@ extern "C" { #define BSP_ARM_GIC_CPUIF_BASE 0xf8f00100 +#define BSP_ARM_A9MPCORE_GT_BASE 0xf8f00200 + #define BSP_ARM_A9MPCORE_PT_BASE 0xf8f00600 #define BSP_ARM_GIC_DIST_BASE 0xf8f01000 -- cgit v1.2.3