summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc
diff options
context:
space:
mode:
authorAlexander Krutwig <alexander.krutwig@embedded-brains.de>2015-04-01 15:33:25 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-20 08:40:34 +0200
commit75acd9e69f906cbd880a17ee4ca705ad7caa92c0 (patch)
tree71529028154cb323286b02392def2e5277eed312 /c/src/lib/libbsp/powerpc
parenttimecounter: Use in RTEMS (diff)
downloadrtems-75acd9e69f906cbd880a17ee4ca705ad7caa92c0.tar.bz2
bsps: Convert clock drivers to use a timecounter
Update #2271.
Diffstat (limited to 'c/src/lib/libbsp/powerpc')
-rw-r--r--c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c96
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c61
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/configure.ac4
-rw-r--r--c/src/lib/libbsp/powerpc/shared/clock/clock.c56
4 files changed, 114 insertions, 103 deletions
diff --git a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
index 5743dcff35..5724f9bf4b 100644
--- a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
+++ b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c
@@ -26,14 +26,40 @@
#include <mpc55xx/regs.h>
+#include <rtems/timecounter.h>
+
void Clock_isr(void *arg);
-static uint64_t mpc55xx_clock_factor;
+static rtems_timecounter_simple mpc55xx_tc;
#if defined(MPC55XX_CLOCK_EMIOS_CHANNEL)
#include <mpc55xx/emios.h>
+static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc)
+{
+ return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CCNTR.R;
+}
+
+static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.B.FLAG != 0;
+}
+
+static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_upcounter_get(
+ tc,
+ mpc55xx_tc_get,
+ mpc55xx_tc_is_pending
+ );
+}
+
+static void mpc55xx_tc_tick(void)
+{
+ rtems_timecounter_simple_upcounter_tick(&mpc55xx_tc, mpc55xx_tc_get);
+}
+
static void mpc55xx_clock_at_tick(void)
{
union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
@@ -60,6 +86,7 @@ static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
static void mpc55xx_clock_initialize(void)
{
+ uint32_t mask;
volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
@@ -68,8 +95,6 @@ static void mpc55xx_clock_initialize(void)
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint64_t interval = (reference_clock * us_per_tick) / 1000000;
- mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock;
-
/* Apply prescaler */
if (prescaler > 0) {
interval /= (uint64_t) prescaler;
@@ -110,6 +135,13 @@ static void mpc55xx_clock_initialize(void)
ccr.B.FEN = 1;
ccr.B.FREN = 1;
regs->CCR.R = ccr.R;
+
+ rtems_timecounter_simple_install(
+ &mpc55xx_tc,
+ reference_clock,
+ interval,
+ mpc55xx_tc_get_timecount
+ );
}
static void mpc55xx_clock_cleanup(void)
@@ -122,21 +154,31 @@ static void mpc55xx_clock_cleanup(void)
regs->CCR.R = ccr.R;
}
-static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void)
+#elif defined(MPC55XX_CLOCK_PIT_CHANNEL)
+
+static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc)
{
- volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
- uint64_t c = regs->CCNTR.R;
- union EMIOS_CSR_tag csr = { .R = regs->CSR.R };
- uint64_t k = mpc55xx_clock_factor;
+ return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].CVAL.R;
+}
- if (csr.B.FLAG != 0) {
- c = regs->CCNTR.R + regs->CADR.R + 1;
- }
+static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc)
+{
+ return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].TFLG.B.TIF != 0;
+}
- return (uint32_t) ((c * k) >> 32);
+static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
+{
+ return rtems_timecounter_simple_downcounter_get(
+ tc,
+ mpc55xx_tc_get,
+ mpc55xx_tc_is_pending
+ );
}
-#elif defined(MPC55XX_CLOCK_PIT_CHANNEL)
+static void mpc55xx_tc_tick(void)
+{
+ rtems_timecounter_simple_downcounter_tick(&mpc55xx_tc, mpc55xx_tc_get);
+}
static void mpc55xx_clock_at_tick(void)
{
@@ -166,6 +208,7 @@ static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
static void mpc55xx_clock_initialize(void)
{
+ uint32_t mask;
volatile PIT_RTI_CHANNEL_tag *channel =
&PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
uint64_t reference_clock = bsp_clock_speed;
@@ -174,11 +217,16 @@ static void mpc55xx_clock_initialize(void)
PIT_RTI_PITMCR_32B_tag pitmcr = { .B = { .FRZ = 1 } };
PIT_RTI_TCTRL_32B_tag tctrl = { .B = { .TIE = 1, .TEN = 1 } };
- mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock;
-
PIT_RTI.PITMCR.R = pitmcr.R;
channel->LDVAL.R = interval;
channel->TCTRL.R = tctrl.R;
+
+ rtems_timecounter_simple_install(
+ &mpc55xx_tc,
+ reference_clock,
+ interval,
+ mpc55xx_tc_get_timecount
+ );
}
static void mpc55xx_clock_cleanup(void)
@@ -189,23 +237,9 @@ static void mpc55xx_clock_cleanup(void)
channel->TCTRL.R = 0;
}
-static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void)
-{
- volatile PIT_RTI_CHANNEL_tag *channel =
- &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
- uint32_t c = channel->CVAL.R;
- uint32_t i = channel->LDVAL.R;
- uint64_t k = mpc55xx_clock_factor;
-
- if (channel->TFLG.B.TIF != 0) {
- c = channel->CVAL.R - i;
- }
-
- return (uint32_t) (((i - c) * k) >> 32);
-}
-
#endif
+#define Clock_driver_timecounter_tick() mpc55xx_tc_tick()
#define Clock_driver_support_at_tick() \
mpc55xx_clock_at_tick()
#define Clock_driver_support_initialize_hardware() \
@@ -217,8 +251,6 @@ static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void)
} while (0)
#define Clock_driver_support_shutdown_hardware() \
mpc55xx_clock_cleanup()
-#define Clock_driver_nanoseconds_since_last_tick \
- mpc55xx_clock_nanoseconds_since_last_tick
/* Include shared source clock driver code */
#include "../../../../libbsp/shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c
index 039edde46e..c6300e254f 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c
@@ -7,10 +7,10 @@
*/
/*
- * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
@@ -20,6 +20,8 @@
* http://www.rtems.org/license/LICENSE.
*/
+#include <rtems/timecounter.h>
+
#include <libcpu/powerpc-utility.h>
#include <bsp.h>
@@ -29,10 +31,6 @@
/* This is defined in clockdrv_shell.h */
static rtems_isr Clock_isr(void *arg);
-static uint32_t qoriq_clock_last_ccr;
-
-static uint32_t qoriq_clock_nanoseconds_per_timer_tick;
-
static volatile qoriq_pic_global_timer *const qoriq_clock =
#if QORIQ_CLOCK_TIMER < 4
&qoriq.pic.gta [QORIQ_CLOCK_TIMER];
@@ -40,8 +38,17 @@ static volatile qoriq_pic_global_timer *const qoriq_clock =
&qoriq.pic.gtb [QORIQ_CLOCK_TIMER - 4];
#endif
+static volatile qoriq_pic_global_timer *const qoriq_timecounter =
+ #if QORIQ_CLOCK_TIMECOUNTER < 4
+ &qoriq.pic.gta [QORIQ_CLOCK_TIMECOUNTER];
+ #else
+ &qoriq.pic.gtb [QORIQ_CLOCK_TIMECOUNTER - 4];
+ #endif
+
#define CLOCK_INTERRUPT (QORIQ_IRQ_GT_BASE + QORIQ_CLOCK_TIMER)
+static struct timecounter qoriq_clock_tc;
+
static void qoriq_clock_handler_install(rtems_isr_entry *old_isr)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -77,18 +84,28 @@ static void qoriq_clock_handler_install(rtems_isr_entry *old_isr)
}
}
+static uint32_t qoriq_clock_get_timecount(struct timecounter *tc)
+{
+ uint32_t ccr = qoriq_timecounter->ccr;
+
+ return GTCCR_COUNT_GET(-ccr);
+}
+
static void qoriq_clock_initialize(void)
{
uint32_t timer_frequency = BSP_bus_frequency / 8;
- uint32_t nanoseconds_per_second = 1000000000;
uint32_t interval = (uint32_t) (((uint64_t) timer_frequency
* (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000);
- qoriq_clock_nanoseconds_per_timer_tick =
- nanoseconds_per_second / timer_frequency;
-
qoriq_clock->bcr = GTBCR_COUNT(interval);
- qoriq_clock_last_ccr = qoriq_clock->ccr;
+
+ qoriq_timecounter->bcr = GTBCR_COUNT(0xffffffff);
+
+ qoriq_clock_tc.tc_get_timecount = qoriq_clock_get_timecount;
+ qoriq_clock_tc.tc_counter_mask = GTCCR_COUNT_GET(0xffffffff);
+ qoriq_clock_tc.tc_frequency = timer_frequency;
+ qoriq_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&qoriq_clock_tc);
}
static void qoriq_clock_cleanup(void)
@@ -107,33 +124,13 @@ static void qoriq_clock_cleanup(void)
}
}
-static void qoriq_clock_at_tick(void)
-{
- qoriq_clock_last_ccr = qoriq_clock->ccr;
-}
-
-static uint32_t qoriq_clock_nanoseconds_since_last_tick(void)
-{
- uint32_t ccr = qoriq_clock->ccr;
- uint32_t bcr = qoriq_clock->bcr;
-
- if ((ccr & GTCCR_TOG) != (qoriq_clock_last_ccr & GTCCR_TOG)) {
- bcr += bcr;
- }
-
- return (bcr - GTCCR_COUNT_GET(ccr)) * qoriq_clock_nanoseconds_per_timer_tick;
-}
-
-#define Clock_driver_support_at_tick() \
- qoriq_clock_at_tick()
+#define Clock_driver_support_at_tick()
#define Clock_driver_support_initialize_hardware() \
qoriq_clock_initialize()
#define Clock_driver_support_install_isr(clock_isr, old_isr) \
qoriq_clock_handler_install(&old_isr)
#define Clock_driver_support_shutdown_hardware() \
qoriq_clock_cleanup()
-#define Clock_driver_nanoseconds_since_last_tick \
- qoriq_clock_nanoseconds_since_last_tick
/* Include shared source clock driver code */
#include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/powerpc/qoriq/configure.ac b/c/src/lib/libbsp/powerpc/qoriq/configure.ac
index f1ff103d7c..409ac193c4 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/configure.ac
+++ b/c/src/lib/libbsp/powerpc/qoriq/configure.ac
@@ -154,6 +154,10 @@ RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[qoriq_core_1],[4])
RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[*],[0])
RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMER],[global timer used for system clock, 0..3 maps to A0..A3, and 4..7 maps to B0..B3])
+RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMECOUNTER],[qoriq_core_1],[5])
+RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMECOUNTER],[*],[1])
+RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMECOUNTER],[global timer used for the timecounter, 0..3 maps to A0..A3, and 4..7 maps to B0..B3])
+
RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[qoriq_t2080*],[QORIQ_CHIP_T2080])
RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[qoriq_t4240*],[QORIQ_CHIP_T4240])
RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[*],[QORIQ_CHIP_P1020])
diff --git a/c/src/lib/libbsp/powerpc/shared/clock/clock.c b/c/src/lib/libbsp/powerpc/shared/clock/clock.c
index e9b1d4d24a..d2f2d0d1b0 100644
--- a/c/src/lib/libbsp/powerpc/shared/clock/clock.c
+++ b/c/src/lib/libbsp/powerpc/shared/clock/clock.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
@@ -22,6 +22,7 @@
#include <rtems.h>
#include <rtems/clockdrv.h>
+#include <rtems/timecounter.h>
#include <libcpu/powerpc-utility.h>
#include <bsp/vectors.h>
@@ -46,7 +47,12 @@ static uint32_t ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
static uint32_t ppc_clock_next_time_base;
-static uint64_t ppc_clock_factor;
+static struct timecounter ppc_tc;
+
+static uint32_t ppc_get_timecount(struct timecounter *tc)
+{
+ return ppc_time_base();
+}
static void ppc_clock_no_tick(void)
{
@@ -161,28 +167,6 @@ static int ppc_clock_exception_handler_ppc405(BSP_Exception_frame *frame, unsign
return 0;
}
-static uint32_t ppc_clock_nanoseconds_since_last_tick(void)
-{
- uint64_t k = ppc_clock_factor;
- uint32_t c = ppc_decrementer_register();
- uint32_t i = ppc_clock_decrementer_value + 1;
-
- return (uint32_t) (((i - c) * k) >> 32);
-}
-
-static uint32_t ppc_clock_nanoseconds_since_last_tick_ppc405(void)
-{
- uint64_t k = ppc_clock_factor;
- uint32_t i = ppc_clock_decrementer_value;
- uint32_t c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT);
-
- if ((PPC_SPECIAL_PURPOSE_REGISTER(PPC405_TSR) & BOOKE_TSR_DIS) != 0) {
- c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT) + i;
- }
-
- return (uint32_t) ((c * k) >> 32);
-}
-
void Clock_exit(void)
{
/* Set the decrementer to the maximum value */
@@ -201,18 +185,12 @@ rtems_device_driver Clock_initialize(
uint64_t frequency = bsp_time_base_frequency;
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);
+ uint32_t mask;
/*
* Set default ticker.
- *
- * The function rtems_clock_tick() returns a status code. This value
- * will be discarded since the RTEMS documentation claims that it is
- * always successful.
*/
- ppc_clock_tick = (void (*)(void)) rtems_clock_tick;
-
- /* Factor for nano seconds extension */
- ppc_clock_factor = (1000000000ULL << 32) / frequency;
+ ppc_clock_tick = rtems_timecounter_tick;
if (ppc_cpu_is_bookE() != PPC_BOOKE_405) {
/* Decrementer value */
@@ -223,10 +201,6 @@ rtems_device_driver Clock_initialize(
ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
}
-
- /* Set the nanoseconds since last tick handler */
- rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick);
-
if (ppc_cpu_is_bookE()) {
/* Set decrementer auto-reload value */
PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);
@@ -253,9 +227,6 @@ rtems_device_driver Clock_initialize(
/* PIT interval value */
ppc_clock_decrementer_value = interval;
- /* Set the nanoseconds since last tick handler */
- rtems_clock_set_nanoseconds_extension(ppc_clock_nanoseconds_since_last_tick_ppc405);
-
/* Install exception handler */
ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405);
@@ -266,5 +237,12 @@ rtems_device_driver Clock_initialize(
PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval);
}
+ /* Install timecounter */
+ ppc_tc.tc_get_timecount = ppc_get_timecount;
+ ppc_tc.tc_counter_mask = 0xffffffff;
+ ppc_tc.tc_frequency = frequency;
+ ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&ppc_tc);
+
return RTEMS_SUCCESSFUL;
}