summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-02-10 12:21:24 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-02-10 16:58:03 +0100
commit0df8d7f20d1e1e0cddf52f3338989f4fdf2cd8ad (patch)
treec13e559b3774f5e08eb6778f74f1137325bf1ffe
parentbsps/arm: Include missing header file (diff)
downloadrtems-0df8d7f20d1e1e0cddf52f3338989f4fdf2cd8ad.tar.bz2
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.
-rw-r--r--c/src/lib/libbsp/arm/realview-pbx-a9/include/bsp.h2
-rw-r--r--c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c76
-rw-r--r--c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h16
-rw-r--r--c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h11
-rw-r--r--c/src/lib/libbsp/arm/xilinx-zynq/include/bsp.h2
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 <bsp/arm-a9mpcore-regs.h>
#include <bsp/arm-a9mpcore-clock.h>
-#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