[PATCH 45/45] bsps: Convert clock drivers to use a timecounter

Sebastian Huber sebastian.huber at embedded-brains.de
Fri May 15 11:47:52 UTC 2015


From: Alexander Krutwig <alexander.krutwig at embedded-brains.de>

Update #2271.
---
 c/src/lib/libbsp/arm/beagle/clock.c                |  35 ++----
 c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c      |   2 +
 c/src/lib/libbsp/arm/gba/clock/clockdrv.c          |   2 +
 c/src/lib/libbsp/arm/nds/clock/clock.c             |   2 +
 c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c  |  12 +-
 .../libbsp/arm/shared/arm-a9mpcore-clock-config.c  |  48 +++-----
 .../arm/shared/armv7m/clock/armv7m-clock-config.c  |  65 ++++++-----
 .../libbsp/arm/shared/lpc/clock/lpc-clock-config.c |  50 ++++++---
 c/src/lib/libbsp/arm/tms570/clock/clock.c          |  40 +++----
 c/src/lib/libbsp/i386/pc386/clock/ckinit.c         | 125 ++++-----------------
 c/src/lib/libbsp/lm32/shared/clock/ckinit.c        |   2 +
 .../libbsp/lm32/shared/milkymist_clock/ckinit.c    |   2 +
 c/src/lib/libbsp/m68k/av5282/clock/clock.c         |   2 +
 c/src/lib/libbsp/m68k/gen68360/clock/clock.c       |   2 +
 c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c     |   2 +
 c/src/lib/libbsp/m68k/mcf52235/clock/clock.c       |  50 +++++----
 c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c       |  44 ++++++--
 c/src/lib/libbsp/m68k/mcf5235/clock/clock.c        |   2 +
 c/src/lib/libbsp/m68k/mcf5329/clock/clock.c        |  49 ++++----
 c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c    |   2 +
 c/src/lib/libbsp/m68k/uC5282/clock/clock.c         |  48 ++++++--
 c/src/lib/libbsp/mips/csb350/clock/clockdrv.c      |   2 +
 .../lib/libbsp/mips/genmongoosev/clock/clockdrv.c  |   2 +
 c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c     |   2 +
 c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c    |   1 +
 c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c    |   2 +
 c/src/lib/libbsp/mips/shared/clock/clockdrv.c      |  10 +-
 c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c     |   2 +
 .../lib/libbsp/or1k/generic_or1k/clock/clockdrv.c  |  50 +++++----
 .../libbsp/powerpc/mpc55xxevb/clock/clock-config.c |  96 ++++++++++------
 .../lib/libbsp/powerpc/qoriq/clock/clock-config.c  |  51 ++++-----
 c/src/lib/libbsp/powerpc/shared/clock/clock.c      |  56 +++------
 c/src/lib/libbsp/shared/clock_driver_simidle.c     |   2 +
 c/src/lib/libbsp/shared/clockdrv_shell.h           |  28 +++--
 c/src/lib/libbsp/sparc/erc32/clock/ckinit.c        |  77 +++++++++++--
 c/src/lib/libbsp/sparc/leon2/clock/ckinit.c        |  52 ++++++---
 c/src/lib/libbsp/sparc/leon3/clock/ckinit.c        |  97 +++++++++++-----
 c/src/lib/libbsp/sparc64/shared/clock/ckinit.c     |   2 +
 c/src/lib/libcpu/arm/at91rm9200/clock/clock.c      |  23 +---
 c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c      |  53 ++++++---
 c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c    |   3 +
 c/src/lib/libcpu/arm/pxa255/clock/clock.c          |   2 +
 c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c      |  14 +--
 c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c    |  91 +++------------
 44 files changed, 683 insertions(+), 621 deletions(-)

diff --git a/c/src/lib/libbsp/arm/beagle/clock.c b/c/src/lib/libbsp/arm/beagle/clock.c
index 66aba1b..912d904 100644
--- a/c/src/lib/libbsp/arm/beagle/clock.c
+++ b/c/src/lib/libbsp/arm/beagle/clock.c
@@ -15,11 +15,12 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <bsp.h>
 
 #include <libcpu/omap_timer.h>
 
-#ifdef ARM_MULTILIB_ARCH_V4
+static struct timecounter beagle_clock_tc;
 
 static omap_timer_registers_t regs_v1 = {
   .TIDR = OMAP3_TIMER_TIDR,
@@ -115,8 +116,6 @@ static struct omap_timer *timer = &am335x_timer;
 
 #endif
 
-static int done = 0;
-
 #if IS_AM335X
 #define FRCLOCK_HZ (16*1500000)
 #endif
@@ -181,20 +180,14 @@ omap3_frclock_init(void)
   /* Start timer, without prescaler */
   mmio_set(fr_timer->base + fr_timer->regs->TCLR,
       OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
-  done = 1;
 }
 
-static inline uint32_t
-read_frc(void)
+static uint32_t
+beagle_clock_get_timecount(struct timecounter *tc)
 {
-  if (done == 0) {
-    return 0;
-  }
   return mmio_read(fr_timer->base + fr_timer->regs->TCRR);
 }
 
-static uint32_t last_tick_nanoseconds;
-
 static void
 beagle_clock_initialize(void)
 {
@@ -262,12 +255,16 @@ beagle_clock_initialize(void)
   while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
 #endif
 
+  /* Install timecounter */ \
+  beagle_clock_tc.tc_get_timecount = beagle_clock_get_timecount;
+  beagle_clock_tc.tc_counter_mask = 0xffffffff;
+  beagle_clock_tc.tc_frequency = FRCLOCK_HZ;
+  beagle_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&beagle_clock_tc);
 }
 
 static void beagle_clock_at_tick(void)
 {
-  last_tick_nanoseconds = read_frc();
-
   mmio_write(timer->base + timer->regs->TISR,
     OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
       OMAP3_TISR_TCAR_IT_FLAG);
@@ -315,14 +312,6 @@ static void beagle_clock_cleanup(void)
   mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST);
 }
 
-static inline uint32_t beagle_clock_nanoseconds_since_last_tick(void)
-{
-  /* this arithmetic also works if read_frc() wraps around, as long
-   * as the subtraction wraps around too
-   */
-  return (read_frc() - (uint64_t) last_tick_nanoseconds) * 1000000000 / FRCLOCK_HZ;
-}
-
 #define Clock_driver_support_at_tick() beagle_clock_at_tick()
 #define Clock_driver_support_initialize_hardware() beagle_clock_initialize()
 #define Clock_driver_support_install_isr(isr, old_isr) \
@@ -332,10 +321,6 @@ static inline uint32_t beagle_clock_nanoseconds_since_last_tick(void)
   } while (0)
 
 #define Clock_driver_support_shutdown_hardware() beagle_clock_cleanup()
-#define Clock_driver_nanoseconds_since_last_tick \
-  beagle_clock_nanoseconds_since_last_tick
 
 /* Include shared source clock driver code */
 #include "../../shared/clockdrv_shell.h"
-
-#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c b/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c
index 499a279..121b2c9 100644
--- a/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c
+++ b/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c
@@ -68,4 +68,6 @@ void Clock_isr(void * arg);
     assert(status == RTEMS_SUCCESSFUL);             \
   } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/arm/gba/clock/clockdrv.c b/c/src/lib/libbsp/arm/gba/clock/clockdrv.c
index 72d0b81..ff17111 100644
--- a/c/src/lib/libbsp/arm/gba/clock/clockdrv.c
+++ b/c/src/lib/libbsp/arm/gba/clock/clockdrv.c
@@ -92,4 +92,6 @@ void Clock_driver_support_initialize_hardware(void)
   GBA_REG_TM3CNT = (0x00c0|GBA_TMCNT_PS);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/arm/nds/clock/clock.c b/c/src/lib/libbsp/arm/nds/clock/clock.c
index a24f8cc..1e239d4 100644
--- a/c/src/lib/libbsp/arm/nds/clock/clock.c
+++ b/c/src/lib/libbsp/arm/nds/clock/clock.c
@@ -81,4 +81,6 @@ void Clock_driver_support_initialize_hardware (void)
   TIMER_DATA (0) = TIMER_FREQ_64 ((uint16_t) freq);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
index 533873c..f765485 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
+++ b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
@@ -72,14 +72,6 @@ static void raspberrypi_clock_cleanup(void)
   }
 }
 
-/*
- *  Return the nanoseconds since last tick
- */
-static uint32_t raspberrypi_clock_nanoseconds_since_last_tick(void)
-{
-  return 0;
-}
-
 #define Clock_driver_support_at_tick() raspberrypi_clock_at_tick()
 
 #define Clock_driver_support_initialize_hardware() raspberrypi_clock_initialize()
@@ -92,8 +84,6 @@ static uint32_t raspberrypi_clock_nanoseconds_since_last_tick(void)
 
 #define Clock_driver_support_shutdown_hardware() raspberrypi_clock_cleanup()
 
-#define Clock_driver_nanoseconds_since_last_tick \
-  raspberrypi_clock_nanoseconds_since_last_tick
-
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
 
 #include "../../../shared/clockdrv_shell.h"
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 f2ce07e..8e2e153 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-2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013-2015 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -17,14 +17,11 @@
 #include <bsp/irq.h>
 #include <bsp/arm-a9mpcore-regs.h>
 #include <bsp/arm-a9mpcore-clock.h>
+#include <rtems/timecounter.h>
 
 #define A9MPCORE_GT ((volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE)
 
-static uint64_t a9mpcore_clock_last_tick_k;
-
-static uint32_t a9mpcore_clock_last_tick_cmpvallower;
-
-static uint32_t a9mpcore_clock_autoinc;
+static struct timecounter a9mpcore_tc;
 
 /* This is defined in clockdrv_shell.h */
 void Clock_isr(rtems_irq_hdl_param arg);
@@ -39,13 +36,6 @@ static void a9mpcore_clock_at_tick(void)
 {
   volatile a9mpcore_gt *gt = A9MPCORE_GT;
 
-  /*
-   * FIXME: Now the _TOD_Get_with_nanoseconds() yields wrong values until
-   * _TOD_Tickle_ticks() managed to update the uptime.  See also PR2180.
-   */
-  a9mpcore_clock_last_tick_cmpvallower =
-    gt->cmpvallower - a9mpcore_clock_autoinc;
-
   gt->irqst = A9MPCORE_GT_IRQST_EFLG;
 }
 
@@ -80,6 +70,13 @@ static uint64_t a9mpcore_clock_get_counter(volatile a9mpcore_gt *gt)
   return ((uint64_t) cu2 << 32) | cl;
 }
 
+static uint32_t a9mpcore_clock_get_timecount(struct timecounter *tc)
+{
+  volatile a9mpcore_gt *gt = A9MPCORE_GT;
+
+  return gt->cntrlower;
+}
+
 static void a9mpcore_clock_initialize(void)
 {
   volatile a9mpcore_gt *gt = A9MPCORE_GT;
@@ -98,14 +95,16 @@ static void a9mpcore_clock_initialize(void)
   gt->cmpvalupper = (uint32_t) (cmpval >> 32);
   gt->autoinc = interval;
 
-  a9mpcore_clock_last_tick_k = (UINT64_C(1000000000) << 32) / periphclk;
-  a9mpcore_clock_last_tick_cmpvallower = (uint32_t) cmpval - interval;
-  a9mpcore_clock_autoinc = interval;
-
   gt->ctrl = A9MPCORE_GT_CTRL_AUTOINC_EN
     | A9MPCORE_GT_CTRL_IRQ_EN
     | A9MPCORE_GT_CTRL_COMP_EN
     | A9MPCORE_GT_CTRL_TMR_EN;
+
+  a9mpcore_tc.tc_get_timecount = a9mpcore_clock_get_timecount;
+  a9mpcore_tc.tc_counter_mask = 0xffffffff;
+  a9mpcore_tc.tc_frequency = periphclk;
+  a9mpcore_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&a9mpcore_tc);
 }
 
 CPU_Counter_ticks _CPU_Counter_read(void)
@@ -147,16 +146,6 @@ static void a9mpcore_clock_cleanup(void)
   }
 }
 
-static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void)
-{
-  volatile a9mpcore_gt *gt = A9MPCORE_GT;
-  uint64_t k = a9mpcore_clock_last_tick_k;
-  uint32_t n = a9mpcore_clock_last_tick_cmpvallower;
-  uint32_t c = gt->cntrlower;
-
-  return (uint32_t) (((c - n) * k) >> 32);
-}
-
 #define Clock_driver_support_at_tick() \
   a9mpcore_clock_at_tick()
 
@@ -165,15 +154,12 @@ static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void)
 
 #define Clock_driver_support_install_isr(isr, old_isr) \
   do { \
-    a9mpcore_clock_handler_install();	\
+    a9mpcore_clock_handler_install(); \
     old_isr = NULL; \
   } while (0)
 
 #define Clock_driver_support_shutdown_hardware() \
   a9mpcore_clock_cleanup()
 
-#define Clock_driver_nanoseconds_since_last_tick \
-  a9mpcore_clock_nanoseconds_since_last_tick
-
 /* Include shared source clock driver code */
 #include "../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
index 8e4ae33..e78684c 100644
--- a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
+++ b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
@@ -13,6 +13,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <rtems/score/armv7m.h>
 
 #include <bsp.h>
@@ -22,15 +23,35 @@
 /* This is defined in clockdrv_shell.h */
 static void Clock_isr(void *arg);
 
-#define _ARMV7M_Systick_get_factor(freq) \
-  ((1000000000ULL << 32) / (freq))
+static rtems_timecounter_simple _ARMV7M_TC;
 
-#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
-  #define _ARMV7M_Systick_factor \
-    _ARMV7M_Systick_get_factor(BSP_ARMV7M_SYSTICK_FREQUENCY)
-#else
-  static uint64_t _ARMV7M_Systick_factor;
-#endif
+static uint32_t _ARMV7M_TC_get(rtems_timecounter_simple *tc)
+{
+  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
+
+  return systick->cvr;
+}
+
+static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *tc)
+{
+  volatile ARMV7M_SCB *scb = _ARMV7M_SCB;
+
+  return ((scb->icsr & ARMV7M_SCB_ICSR_PENDSTSET) != 0);
+}
+
+static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    _ARMV7M_TC_get,
+    _ARMV7M_TC_is_pending
+  );
+}
+
+static void _ARMV7M_TC_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(&_ARMV7M_TC, _ARMV7M_TC_get);
+}
 
 static void _ARMV7M_Systick_at_tick(void)
 {
@@ -67,15 +88,18 @@ static void _ARMV7M_Systick_initialize(void)
   uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
   uint64_t interval = (freq * us_per_tick) / 1000000ULL;
 
-  #ifndef BSP_ARMV7M_SYSTICK_FREQUENCY
-    _ARMV7M_Systick_factor = _ARMV7M_Systick_get_factor(freq);
-  #endif
-
   systick->rvr = (uint32_t) interval;
   systick->cvr = 0;
   systick->csr = ARMV7M_SYSTICK_CSR_ENABLE
     | ARMV7M_SYSTICK_CSR_TICKINT
     | ARMV7M_SYSTICK_CSR_CLKSOURCE;
+
+  rtems_timecounter_simple_install(
+    &_ARMV7M_TC,
+    freq,
+    interval,
+    _ARMV7M_TC_get_timecount
+  );
 }
 
 static void _ARMV7M_Systick_cleanup(void)
@@ -85,19 +109,7 @@ static void _ARMV7M_Systick_cleanup(void)
   systick->csr = 0;
 }
 
-static uint32_t _ARMV7M_Systick_nanoseconds_since_last_tick(void)
-{
-  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
-  volatile ARMV7M_SCB *scb = _ARMV7M_SCB;
-  uint32_t rvr = systick->rvr;
-  uint32_t c = rvr - systick->cvr;
-
-  if ((scb->icsr & ARMV7M_SCB_ICSR_PENDSTSET) != 0) {
-    c = rvr - systick->cvr + rvr;
-  }
-
-  return (uint32_t) ((c * _ARMV7M_Systick_factor) >> 32);
-}
+#define Clock_driver_timecounter_tick() _ARMV7M_TC_tick()
 
 #define Clock_driver_support_at_tick() \
   _ARMV7M_Systick_at_tick()
@@ -114,9 +126,6 @@ static uint32_t _ARMV7M_Systick_nanoseconds_since_last_tick(void)
 #define Clock_driver_support_shutdown_hardware() \
   _ARMV7M_Systick_cleanup()
 
-#define Clock_driver_nanoseconds_since_last_tick \
-  _ARMV7M_Systick_nanoseconds_since_last_tick
-
 /* Include shared source clock driver code */
 #include "../../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c b/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c
index 05c94a6..e3861fe 100644
--- a/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c
+++ b/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c
@@ -21,6 +21,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 
 #include <bsp/lpc-clock-config.h>
 #include <bsp/lpc-timer.h>
@@ -33,6 +34,32 @@ void Clock_isr(rtems_irq_hdl_param arg);
 static volatile lpc_timer *const lpc_clock =
   (volatile lpc_timer *) LPC_CLOCK_TIMER_BASE;
 
+static rtems_timecounter_simple lpc_clock_tc;
+
+static uint32_t lpc_clock_tc_get(rtems_timecounter_simple *tc)
+{
+  return lpc_clock->tc;
+}
+
+static bool lpc_clock_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (lpc_clock->ir & LPC_TIMER_IR_MR0) != 0;
+}
+
+static uint32_t lpc_clock_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_upcounter_get(
+    tc,
+    lpc_clock_tc_get,
+    lpc_clock_tc_is_pending
+  );
+}
+
+static void lpc_clock_tc_tick(void)
+{
+  rtems_timecounter_simple_upcounter_tick(&lpc_clock_tc, lpc_clock_tc_get);
+}
+
 static void lpc_clock_at_tick(void)
 {
   lpc_clock->ir = LPC_TIMER_IR_MR0;
@@ -56,6 +83,7 @@ static void lpc_clock_handler_install(void)
 
 static void lpc_clock_initialize(void)
 {
+  uint32_t mask;
   uint64_t interval = ((uint64_t) LPC_CLOCK_REFERENCE
     * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000;
 
@@ -85,6 +113,14 @@ static void lpc_clock_initialize(void)
 
   /* Enable timer */
   lpc_clock->tcr = LPC_TIMER_TCR_EN;
+
+  /* Install timecounter */
+  rtems_timecounter_simple_install(
+    &lpc_clock_tc,
+    LPC_CLOCK_REFERENCE,
+    interval,
+    lpc_clock_tc_get_timecount
+  );
 }
 
 static void lpc_clock_cleanup(void)
@@ -105,17 +141,7 @@ static void lpc_clock_cleanup(void)
   }
 }
 
-static uint32_t lpc_clock_nanoseconds_since_last_tick(void)
-{
-  uint64_t k = (1000000000ULL << 32) / LPC_CLOCK_REFERENCE;
-  uint64_t c = lpc_clock->tc;
-
-  if ((lpc_clock->ir & LPC_TIMER_IR_MR0) != 0) {
-    c = lpc_clock->tc + lpc_clock->mr0;
-  }
-
-  return (uint32_t) ((c * k) >> 32);
-}
+#define Clock_driver_timecounter_tick() lpc_clock_tc_tick()
 
 #define Clock_driver_support_at_tick() lpc_clock_at_tick()
 #define Clock_driver_support_initialize_hardware() lpc_clock_initialize()
@@ -126,8 +152,6 @@ static uint32_t lpc_clock_nanoseconds_since_last_tick(void)
   } while (0)
 
 #define Clock_driver_support_shutdown_hardware() lpc_clock_cleanup()
-#define Clock_driver_nanoseconds_since_last_tick \
-  lpc_clock_nanoseconds_since_last_tick
 
 /* Include shared source clock driver code */
 #include "../../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/arm/tms570/clock/clock.c b/c/src/lib/libbsp/arm/tms570/clock/clock.c
index 4dba949..d438a3d 100644
--- a/c/src/lib/libbsp/arm/tms570/clock/clock.c
+++ b/c/src/lib/libbsp/arm/tms570/clock/clock.c
@@ -30,13 +30,14 @@
 #include <bsp/irq.h>
 #include <bsp/tms570-rti.h>
 #include <rtems/counter.h>
+#include <rtems/timecounter.h>
 
-/**
- *  holds HW counter value since last interrupt event
- *  sets in tms570_clock_driver_support_at_tick
- *  used in tms570_clock_driver_nanoseconds_since_last_tick
- */
-static uint32_t tms570_rti_last_tick_fcr0;
+static struct timecounter tms570_rti_tc;
+
+static uint32_t tms570_rti_get_timecount(struct timecounter tc)
+{
+  return TMS570_RTI.RTIFRC0;
+}
 
 /**
  *  @brief Initialize the HW peripheral for clock driver
@@ -72,6 +73,12 @@ static void tms570_clock_driver_support_initialize_hardware( void )
   TMS570_RTI.RTISETINTENA = 0x1;
   /* enable timer */
   TMS570_RTI.RTIGCTRL = 1;
+  /* set timecounter */
+  tms570_rti_tc.tc_get_timecount = tms570_rti_get_timecount;
+  tms570_rti_tc.tc_counter_mask = 0xffffffff;
+  tms570_rti_tc.tc_frequency = BSP_PLL_OUT_CLOCK;
+  tms570_rti_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&tms570_rti_tc);
 }
 
 /**
@@ -82,7 +89,6 @@ static void tms570_clock_driver_support_initialize_hardware( void )
 static void tms570_clock_driver_support_at_tick( void )
 {
   TMS570_RTI.RTIINTFLAG = 0x00000001;
-  tms570_rti_last_tick_fcr0 = TMS570_RTI.RTICOMP0 - TMS570_RTI.RTIUDCP0;
 }
 
 /**
@@ -124,24 +130,6 @@ static void tms570_clock_driver_support_shutdown_hardware( void )
   TMS570_RTI.RTICLEARINTENA = 0x20000;
 }
 
-/**
- * @brief returns the nanoseconds since last tick
- *
- * Return the nanoseconds since last tick
- *
- * @retval x nanoseconds
- *
- */
-static uint32_t tms570_clock_driver_nanoseconds_since_last_tick( void )
-{
-  uint32_t actual_fcr0 = TMS570_RTI.RTIFRC0;
-  uint32_t usec_since_tick;
-
-  usec_since_tick = actual_fcr0 - tms570_rti_last_tick_fcr0;
-
-  return usec_since_tick * 1000;
-}
-
 #define Clock_driver_support_initialize_hardware \
                         tms570_clock_driver_support_initialize_hardware
 #define Clock_driver_support_at_tick \
@@ -150,8 +138,6 @@ static uint32_t tms570_clock_driver_nanoseconds_since_last_tick( void )
                         tms570_clock_driver_support_initialize_hardware
 #define Clock_driver_support_shutdown_hardware \
                         tms570_clock_driver_support_shutdown_hardware
-#define Clock_driver_nanoseconds_since_last_tick \
-                        tms570_clock_driver_nanoseconds_since_last_tick
 
 #define Clock_driver_support_install_isr(Clock_isr, Old_ticker ) \
               tms570_clock_driver_support_install_isr( Clock_isr )
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
index 2782252..44a35bc 100644
--- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
+++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
@@ -28,6 +28,7 @@
 #include <bspopts.h>
 #include <libcpu/cpuModel.h>
 #include <assert.h>
+#include <rtems/timecounter.h>
 
 #define CLOCK_VECTOR 0
 
@@ -39,29 +40,24 @@ uint32_t pc386_clock_click_count;
 void Clock_isr(void *param);
 static void Clock_driver_support_at_tick_empty(void);
 static void clockOff(void);
-static void Clock_driver_support_at_tick_tsc(void);
-static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void);
-static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void);
 static void Clock_isr_handler(void *param);
 
 /*
- * Roughly the number of cycles per tick and per nanosecond. Note that these
+ * Roughly the number of cycles per second. Note that these
  * will be wildly inaccurate if the chip speed changes due to power saving
  * or thermal modes.
  *
  * NOTE: These are only used when the TSC method is used.
  */
-uint64_t pc586_tsc_per_tick;
-uint64_t pc586_nanoseconds_per_tick;
+static uint64_t pc586_tsc_frequency;
 
-uint64_t pc586_tsc_at_tick;
+static struct timecounter pc386_tc;
 
 /* this driver may need to count ISRs per tick */
 #define CLOCK_DRIVER_ISRS_PER_TICK       1
 #define CLOCK_DRIVER_ISRS_PER_TICK_VALUE pc386_isrs_per_tick
 
-/* The driver uses the count in Clock_driver_support_at_tick */
-extern volatile uint32_t Clock_driver_isrs;
+extern volatile uint32_t Clock_driver_ticks;
 
 #define READ_8254( _lsb, _msb )                               \
   do { outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);      \
@@ -74,60 +70,21 @@ extern volatile uint32_t Clock_driver_isrs;
  *  Hooks which get swapped based upon which nanoseconds since last
  *  tick method is preferred.
  */
-void     (*Clock_driver_support_at_tick)(void) = NULL;
-uint32_t (*Clock_driver_nanoseconds_since_last_tick)(void) = NULL;
-
-/*
- *  What do we do at each clock tick?
- */
-static void Clock_driver_support_at_tick_tsc(void)
-{
-  pc586_tsc_at_tick = rdtsc();
-}
-
-static void Clock_driver_support_at_tick_empty(void)
-{
-}
+#define Clock_driver_support_at_tick()
 
 #define Clock_driver_support_install_isr( _new, _old ) \
   do { \
     _old = NULL; \
   } while(0)
 
-/*
- * Get nanoseconds using Pentium-compatible TSC register
- */
-static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void)
+static uint32_t pc386_get_timecount_tsc(struct timecounter *tc)
 {
-  uint64_t                 diff_nsec;
-
-  diff_nsec = rdtsc() - pc586_tsc_at_tick;
-
-  /*
-   * At this point, with a hypothetical 10 GHz CPU clock and 100 Hz tick
-   * clock, diff_nsec <= 27 bits.
-   */
-  diff_nsec *= pc586_nanoseconds_per_tick; /* <= 54 bits */
-  diff_nsec /= pc586_tsc_per_tick;
-
-  if (diff_nsec > pc586_nanoseconds_per_tick)
-    /*
-     * Hmmm... Some drift or rounding. Pin the value to 1 nanosecond before
-     * the next tick.
-     */
-    /*    diff_nsec = pc586_nanoseconds_per_tick - 1; */
-    diff_nsec = 12345;
-
-  return (uint32_t)diff_nsec;
+  return (uint32_t)rdtsc();
 }
 
-/*
- * Get nanoseconds using 8254 timer chip
- */
-static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void)
+static uint32_t pc386_get_timecount_i8254(struct timecounter *tc)
 {
-  uint32_t                 usecs, clicks, isrs;
-  uint32_t                 usecs1, usecs2;
+  uint32_t                 irqs;
   uint8_t                  lsb, msb;
   rtems_interrupt_level    level;
 
@@ -136,34 +93,10 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void)
    */
   rtems_interrupt_disable(level);
     READ_8254(lsb, msb);
-    isrs = Clock_driver_isrs;
+    irqs = Clock_driver_ticks;
   rtems_interrupt_enable(level);
 
-  /*
-   *  Now do the math
-   */
-  /* convert values read into counter clicks */
-  clicks = ((msb << 8) | lsb);
-
-  /* whole ISRs we have done since the last tick */
-  usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr;
-
-  /* the partial ISR we in the middle of now */
-  usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks);
-
-  /* total microseconds */
-  usecs = usecs1 + usecs2;
-  #if 0
-    printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 );
-    printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n",
-    pc386_clock_click_count, clicks,
-    Clock_driver_isrs, pc386_isrs_per_tick,
-    pc386_microseconds_per_isr, usecs );
-  #endif
-
-  /* return it in nanoseconds */
-  return usecs * 1000;
-
+  return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb);
 }
 
 /*
@@ -175,9 +108,6 @@ static void calibrate_tsc(void)
   uint8_t               then_lsb, then_msb, now_lsb, now_msb;
   uint32_t              i;
 
-  pc586_nanoseconds_per_tick =
-    rtems_configuration_get_microseconds_per_tick() * 1000;
-
   /*
    * We just reset the timer, so we know we're at the beginning of a tick.
    */
@@ -204,16 +134,11 @@ static void calibrate_tsc(void)
     } while (1);
   }
 
-  pc586_tsc_per_tick = rdtsc() - begin_time;
-
-  /* Initialize "previous tick" counters */
-  pc586_tsc_at_tick = rdtsc();
+  pc586_tsc_frequency = rdtsc() - begin_time;
 
 #if 0
-  printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_per_tick / 1000000));
+  printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_frequency / 1000000));
 #endif
-
-  pc586_tsc_per_tick /= rtems_clock_get_ticks_per_second();
 }
 
 static void clockOn(void)
@@ -299,24 +224,18 @@ void Clock_driver_support_initialize_hardware(void)
 
   if ( use_8254 ) {
     /* printk( "Use 8254\n" ); */
-    Clock_driver_support_at_tick = Clock_driver_support_at_tick_empty;
-    Clock_driver_nanoseconds_since_last_tick =
-      bsp_clock_nanoseconds_since_last_tick_i8254;
+    pc386_tc.tc_get_timecount = pc386_get_timecount_i8254;
+    pc386_tc.tc_counter_mask = 0xffffffff;
+    pc386_tc.tc_frequency = TIMER_TICK;
   } else {
     /* printk( "Use TSC\n" ); */
-    Clock_driver_support_at_tick = Clock_driver_support_at_tick_tsc;
-    Clock_driver_nanoseconds_since_last_tick =
-      bsp_clock_nanoseconds_since_last_tick_tsc;
+    pc386_tc.tc_get_timecount = pc386_get_timecount_tsc;
+    pc386_tc.tc_counter_mask = 0xffffffff;
+    pc386_tc.tc_frequency = pc586_tsc_frequency;
   }
 
-  /* Shell installs nanosecond handler before calling
-   * Clock_driver_support_initialize_hardware() :-(
-   * so we do it again now that we're ready.
-   */
-  rtems_clock_set_nanoseconds_extension(
-    Clock_driver_nanoseconds_since_last_tick
-  );
-
+  pc386_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&pc386_tc);
   Clock_isr_enabled = true;
 }
 
diff --git a/c/src/lib/libbsp/lm32/shared/clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c
index ae065de..b1f5c8d 100644
--- a/c/src/lib/libbsp/lm32/shared/clock/ckinit.c
+++ b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c
@@ -75,5 +75,7 @@ static void Clock_driver_support_shutdown_hardware(void)
   clockwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_STOP);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
index 65651e6..3230d83 100644
--- a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
+++ b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c
@@ -46,4 +46,6 @@ static void Clock_driver_support_shutdown_hardware(void)
   MM_WRITE(MM_TIMER0_CONTROL, 0);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/av5282/clock/clock.c b/c/src/lib/libbsp/m68k/av5282/clock/clock.c
index 3dded8a..182693f 100644
--- a/c/src/lib/libbsp/m68k/av5282/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/av5282/clock/clock.c
@@ -58,4 +58,6 @@
                             MCF5282_PIT_PCSR_EN;                         \
     } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/gen68360/clock/clock.c b/c/src/lib/libbsp/m68k/gen68360/clock/clock.c
index 78deaf9..3b9d4ca 100644
--- a/c/src/lib/libbsp/m68k/gen68360/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/gen68360/clock/clock.c
@@ -98,4 +98,6 @@ extern int m360_clock_rate;
         m360.pitr |= divisor;                                                 \
     } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c b/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c
index d3f6eb4..d0f28c6 100644
--- a/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c
@@ -98,5 +98,7 @@
     MCF548X_SLT_SCR0 |= (MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \
   } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
index c22393d..7a508a3 100644
--- a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c
@@ -3,6 +3,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <bsp.h>
 
 /*
@@ -10,34 +11,37 @@
  */
 #define CLOCK_VECTOR (64+56)
 
-static uint32_t s_pcntrAtTick = 0;
-static uint32_t s_nanoScale = 0;
+static rtems_timecounter_simple mcf52235_tc;
 
-/*
- * Provide nanosecond extension
- * Interrupts are disabled when this is called
- */
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
+static uint32_t mcf52235_tc_get(rtems_timecounter_simple *tc)
 {
-  uint32_t i;
+  return MCF_PIT1_PCNTR;
+}
 
-  if (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) {
-    i = s_pcntrAtTick + (MCF_PIT1_PMR - MCF_PIT1_PCNTR);
-  }
-  else {
-    i = s_pcntrAtTick - MCF_PIT1_PCNTR;
-  }
-  return i * s_nanoScale;
+static bool mcf52235_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
 }
 
-#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick
+static uint32_t mcf52235_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    mcf52235_tc_get,
+    mcf52235_tc_is_pending
+  );
+}
+
+static void mcf52235_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(&mcf52235_tc, mcf52235_tc_get);
+}
 
 /*
  * Periodic interval timer interrupt handler
  */
 #define Clock_driver_support_at_tick()             \
     do {                                           \
-        s_pcntrAtTick = MCF_PIT1_PCNTR;            \
         MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;         \
     } while (0)                                    \
 
@@ -64,6 +68,7 @@ static void Clock_driver_support_shutdown_hardware(void)
  */
 static void Clock_driver_support_initialize_hardware(void)
 {
+  uint32_t mask;
   int level;
   uint32_t pmr;
   uint32_t preScaleCode = 0;
@@ -76,7 +81,6 @@ static void Clock_driver_support_initialize_hardware(void)
       break;
     preScaleCode++;
   }
-  s_nanoScale = 1000000000 / (clk >> preScaleCode);
 
   MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
     MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
@@ -90,7 +94,15 @@ static void Clock_driver_support_initialize_hardware(void)
   MCF_PIT1_PMR = pmr;
   MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
     MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
-  s_pcntrAtTick = MCF_PIT1_PCNTR;
+
+  rtems_timecounter_simple_install(
+    &mcf52235_tc,
+    clk >> preScaleCode,
+    pmr,
+    mcf52235_tc_get_timecount
+  );
 }
 
+#define Clock_driver_timecounter_tick() mcf52235_tc_tick()
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
index d058126..33fd76c 100644
--- a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c
@@ -3,6 +3,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <bsp.h>
 
 /*
@@ -10,26 +11,37 @@
  */
 #define CLOCK_VECTOR (64+56)
 
-static uint32_t s_pcntrAtTick = 0;
-static uint32_t s_nanoScale = 0;
+static rtems_timecounter_simple mcf5225x_tc;
 
-/*
- * Provide nanosecond extension
- * Interrupts are disabled when this is called
- */
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
+static uint32_t mcf5225x_tc_get(rtems_timecounter_simple *tc)
+{
+  return MCF_PIT1_PCNTR;
+}
+
+static bool mcf5225x_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t mcf5225x_tc_get_timecount(struct timecounter *tc)
 {
-    return MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF ? (s_pcntrAtTick + (MCF_PIT1_PMR - MCF_PIT1_PCNTR)) * s_nanoScale : (s_pcntrAtTick - MCF_PIT1_PCNTR) * s_nanoScale;
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    mcf5225x_tc_get,
+    mcf5225x_tc_is_pending
+  );
 }
 
-#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick
+static void mcf5225x_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(&mcf5225x_tc, mcf5225x_tc_get);
+}
 
 /*
  * Periodic interval timer interrupt handler
  */
 #define Clock_driver_support_at_tick()             \
     do {                                           \
-        s_pcntrAtTick = MCF_PIT1_PCNTR;            \
         MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;         \
     } while (0)                                    \
 
@@ -56,6 +68,7 @@ static void Clock_driver_support_shutdown_hardware(void)
  */
 static void Clock_driver_support_initialize_hardware(void)
 {
+  uint32_t mask;
   int level;
   uint32_t pmr;
   uint32_t preScaleCode = 0;
@@ -68,7 +81,6 @@ static void Clock_driver_support_initialize_hardware(void)
       break;
     preScaleCode++;
   }
-  s_nanoScale = 1000000000 / (clk >> preScaleCode);
 
   MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
     MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
@@ -82,7 +94,15 @@ static void Clock_driver_support_initialize_hardware(void)
   MCF_PIT1_PMR = pmr;
   MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
     MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
-  s_pcntrAtTick = MCF_PIT1_PCNTR;
+
+  rtems_timecounter_simple_install(
+    &mcf5225x_tc,
+    clk >> preScaleCode,
+    pmr,
+    mcf5225x_tc_get_timecount
+  );
 }
 
+#define Clock_driver_timecounter_tick() mcf5225x_tc_tick()
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c
index c057796..95b7f37 100644
--- a/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c
@@ -58,4 +58,6 @@
                             MCF5235_PIT_PCSR_EN;                         \
     } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
index ed11320..94c5bb0 100644
--- a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c
@@ -3,6 +3,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <bsp.h>
 
 /*
@@ -10,36 +11,40 @@
  */
 #define CLOCK_VECTOR (128+46)
 
-static uint32_t s_pcntrAtTick = 0;
-static uint32_t s_nanoScale = 0;
+static rtems_timecounter_simple mcf5329_tc;
 
-/*
- * Provide nanosecond extension
- */
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
+static uint32_t mcf5329_tc_get(rtems_timecounter_simple *tc)
 {
-  uint32_t i;
+  return MCF_PIT3_PCNTR;
+}
 
-  if (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) {
-    i = s_pcntrAtTick + (MCF_PIT3_PMR - MCF_PIT3_PCNTR);
-  } else {
-    i = s_pcntrAtTick - MCF_PIT3_PCNTR;
-  }
-  return i * s_nanoScale;
+static bool mcf5329_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t mcf5329_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    mcf5329_tc_get,
+    mcf5329_tc_is_pending
+  );
 }
 
-#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick
+static void mcf5329_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(&mcf5329_tc, mcf5329_tc_get);
+}
 
 /*
  * Periodic interval timer interrupt handler
  */
 #define Clock_driver_support_at_tick()             \
     do {                                           \
-        s_pcntrAtTick = MCF_PIT3_PCNTR;            \
         MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;         \
     } while (0)                                    \
 
-
 /*
  * Attach clock interrupt handler
  */
@@ -75,8 +80,6 @@ static void Clock_driver_support_initialize_hardware(void)
       break;
     preScaleCode++;
   }
-  s_nanoScale = 1000000000 / (clk >> preScaleCode);
-
   MCF_INTC1_ICR46 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL);
 
   rtems_interrupt_disable(level);
@@ -89,7 +92,15 @@ static void Clock_driver_support_initialize_hardware(void)
   MCF_PIT3_PMR = pmr;
   MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
     MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
-  s_pcntrAtTick = MCF_PIT3_PCNTR;
+
+  rtems_timecounter_simple_install(
+    &mcf5329_tc,
+    clk >> preScaleCode,
+    pmr,
+    mcf5329_tc_get_timecount
+  );
 }
 
+#define Clock_driver_timecounter_tick() mcf5329_tc_tick()
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c b/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c
index 3cf9818..0a78abc 100644
--- a/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c
+++ b/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c
@@ -48,4 +48,6 @@ static void Clock_driver_support_shutdown_hardware(void)
   t->cr  = 0xA0;  /* initialize with timer disabled */
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
index 8636f96..46e045c 100644
--- a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
@@ -12,6 +12,7 @@
  */
 
 #include <rtems.h>
+#include <rtems/timecounter.h>
 #include <bsp.h>
 #include <mcf5282/mcf5282.h>
 
@@ -20,6 +21,32 @@
  */
 #define CLOCK_VECTOR (64+58)
 
+static rtems_timecounter_simple uC5282_tc;
+
+static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc)
+{
+  return MCF5282_PIT3_PCNTR;
+}
+
+static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0;
+}
+
+static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    uC5282_tc_get,
+    uC5282_tc_is_pending
+  );
+}
+
+static void uC5282_tc_tick(void)
+{
+  rtems_timecounter_simple_downcounter_tick(&uC5282_tc, uC5282_tc_get);
+}
+
 /*
  * CPU load counters
  * Place in static RAM so updates don't hit the SDRAM
@@ -31,17 +58,6 @@
 #define NSEC_PER_PITC   __SRAMBASE.nsec_per_pitc
 #define FILTER_SHIFT    6
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-    int i = MCF5282_PIT3_PCNTR;
-    if (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF)
-        i = MCF5282_PIT3_PCNTR - PITC_PER_TICK;
-    return (PITC_PER_TICK - i) * NSEC_PER_PITC;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-    bsp_clock_nanoseconds_since_last_tick
-
 /*
  * Periodic interval timer interrupt handler
  */
@@ -83,7 +99,7 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
  */
 #define Clock_driver_support_initialize_hardware()                       \
     do {                                                                 \
-		unsigned long long N;                                            \
+        unsigned long long N;                                            \
         int level;                                                       \
         int preScaleCode = 0;                                            \
 		N  = bsp_get_CPU_clock_speed();                                  \
@@ -116,6 +132,12 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
                             MCF5282_PIT_PCSR_PIE |                       \
                             MCF5282_PIT_PCSR_RLD |                       \
                             MCF5282_PIT_PCSR_EN;                         \
+         rtems_timecounter_simple_install( \
+           &uC5282_tc, \
+           bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \
+           PITC_PER_TICK, \
+           uC5282_tc_get_timecount \
+         ); \
     } while (0)
 
 /*
@@ -135,4 +157,6 @@ int bsp_cpu_load_percentage(void)
            0;
 }
 
+#define Clock_driver_timecounter_tick() uC5282_tc_tick()
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c b/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c
index c733a1b..537bf7e 100644
--- a/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c
@@ -88,4 +88,6 @@ void au1x00_clock_init(void)
 
 #define Clock_driver_support_shutdown_hardware()
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c b/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c
index 05c1a92..20f730a 100644
--- a/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c
@@ -54,4 +54,6 @@
 #define Clock_driver_support_shutdown_hardware() \
   MONGOOSEV_WRITE_REGISTER( CLOCK_BASE, MONGOOSEV_TIMER_CONTROL_REGISTER, 0 )
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c b/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c
index 4aa1f9e..f3bcbe2 100644
--- a/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c
@@ -55,4 +55,6 @@
 
 #define Clock_driver_support_shutdown_hardware()
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c b/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c
index 4a45c9a..2fb56c6 100644
--- a/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c
@@ -123,5 +123,6 @@
     TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0x0 ); /* Disable timer */ \
   } while(0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
 
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c b/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c
index f50c6d2..59b3452 100644
--- a/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c
@@ -114,4 +114,6 @@ void new_brk_esr(void)
   } while(0)
 
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/mips/shared/clock/clockdrv.c b/c/src/lib/libbsp/mips/shared/clock/clockdrv.c
index 8ee52c6..8b178bb 100644
--- a/c/src/lib/libbsp/mips/shared/clock/clockdrv.c
+++ b/c/src/lib/libbsp/mips/shared/clock/clockdrv.c
@@ -43,17 +43,11 @@ static uint32_t mips_timer_rate = 0;
     mips_enable_in_interrupt_mask(CLOCK_VECTOR_MASK); \
   } while(0)
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-  return 0;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-  bsp_clock_nanoseconds_since_last_tick
-
 #define Clock_driver_support_shutdown_hardware() \
   do { \
     mips_disable_in_interrupt_mask(CLOCK_VECTOR_MASK); \
   } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c b/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c
index 939af651..1656e76 100644
--- a/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c
+++ b/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c
@@ -49,5 +49,7 @@ static void Clock_driver_support_initialize_hardware(void)
   NIOS2_IENABLE(1 << CLOCK_VECTOR);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
index 57e46c1..e01d2e5 100644
--- a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
+++ b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
@@ -22,11 +22,14 @@
 #include <bsp/generic_or1k.h>
 #include <rtems/score/cpu.h>
 #include <rtems/score/or1k-utility.h>
+#include <rtems/timecounter.h>
 
 /* The number of clock cycles before generating a tick timer interrupt. */
 #define TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT     0x09ED9
 #define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS     10
 
+static struct timecounter or1ksim_tc;
+
 /* CPU counter */
 static CPU_Counter_ticks cpu_counter_ticks;
 
@@ -69,8 +72,23 @@ static void generic_or1k_clock_handler_install(
   }
 }
 
+static uint32_t or1ksim_get_timecount(struct timecounter *tc)
+{
+  uint32_t ticks_since_last_timer_interrupt;
+
+  ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
+
+  return cpu_counter_ticks + ticks_since_last_timer_interrupt;
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+  return or1ksim_get_timecount(NULL);
+}
+
 static void generic_or1k_clock_initialize(void)
 {
+  uint64_t frequency = (1000000000 / OR1K_CLOCK_CYCLE_TIME_NANOSECONDS);
   uint32_t TTMR;
 
  /* For TTMR register,
@@ -90,11 +108,15 @@ static void generic_or1k_clock_initialize(void)
   _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR);
   _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0);
 
-  /* Initialize CPU Counter */
-  cpu_counter_ticks = 0;
+  /* Initialize timecounter */
+  or1ksim_tc.tc_get_timecount = or1ksim_get_timecount;
+  or1ksim_tc.tc_counter_mask = 0xffffffff;
+  or1ksim_tc.tc_frequency = frequency;
+  or1ksim_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&or1ksim_tc);
 }
 
- static void generic_or1k_clock_cleanup(void)
+static void generic_or1k_clock_cleanup(void)
 {
  uint32_t sr;
 
@@ -109,24 +131,6 @@ static void generic_or1k_clock_initialize(void)
   _OR1K_mtspr(CPU_OR1K_SPR_TTMR, 0);
 }
 
-/*
- *  Return the nanoseconds since last tick
- */
-static uint32_t generic_or1k_clock_nanoseconds_since_last_tick(void)
-{
-  return
-  TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT * OR1K_CLOCK_CYCLE_TIME_NANOSECONDS;
-}
-
-CPU_Counter_ticks _CPU_Counter_read(void)
-{
-  uint32_t ticks_since_last_timer_interrupt;
-
-  ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
-
-  return cpu_counter_ticks + ticks_since_last_timer_interrupt;
-}
-
 CPU_Counter_ticks _CPU_Counter_difference(
   CPU_Counter_ticks second,
   CPU_Counter_ticks first
@@ -134,6 +138,7 @@ CPU_Counter_ticks _CPU_Counter_difference(
 {
   return second - first;
 }
+
 #define Clock_driver_support_at_tick() generic_or1k_clock_at_tick()
 
 #define Clock_driver_support_initialize_hardware() generic_or1k_clock_initialize()
@@ -146,7 +151,4 @@ CPU_Counter_ticks _CPU_Counter_difference(
 
 #define Clock_driver_support_shutdown_hardware() generic_or1k_clock_cleanup()
 
-#define Clock_driver_nanoseconds_since_last_tick \
-  generic_or1k_clock_nanoseconds_since_last_tick
-
 #include "../../../shared/clockdrv_shell.h"
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 5743dcf..5724f9b 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 039edde..07f7861 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 at 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];
@@ -42,6 +40,8 @@ static volatile qoriq_pic_global_timer *const qoriq_clock =
 
 #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,6 +77,13 @@ 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_clock->ccr;
+
+  return GTCCR_COUNT_GET(ccr);
+}
+
 static void qoriq_clock_initialize(void)
 {
   uint32_t timer_frequency = BSP_bus_frequency / 8;
@@ -84,11 +91,13 @@ static void qoriq_clock_initialize(void)
   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_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 +116,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/shared/clock/clock.c b/c/src/lib/libbsp/powerpc/shared/clock/clock.c
index e9b1d4d..d2f2d0d 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;
 }
diff --git a/c/src/lib/libbsp/shared/clock_driver_simidle.c b/c/src/lib/libbsp/shared/clock_driver_simidle.c
index 0f94b1e..ee4b116 100644
--- a/c/src/lib/libbsp/shared/clock_driver_simidle.c
+++ b/c/src/lib/libbsp/shared/clock_driver_simidle.c
@@ -28,6 +28,8 @@ volatile bool clock_driver_enabled;
     clock_driver_enabled = false; \
   } while (0)
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "clockdrv_shell.h"
 
 /*
diff --git a/c/src/lib/libbsp/shared/clockdrv_shell.h b/c/src/lib/libbsp/shared/clockdrv_shell.h
index 5dbea13..feb8ed3 100644
--- a/c/src/lib/libbsp/shared/clockdrv_shell.h
+++ b/c/src/lib/libbsp/shared/clockdrv_shell.h
@@ -20,6 +20,10 @@
 #include <bsp.h>
 #include <rtems/clockdrv.h>
 
+#ifdef Clock_driver_nanoseconds_since_last_tick
+#error "Update driver to use the timecounter instead of nanoseconds extension"
+#endif
+
 /**
  * @defgroup bsp_clock Clock Support
  *
@@ -39,6 +43,18 @@
   #define Clock_driver_support_find_timer()
 #endif
 
+/*
+ * A specialized clock driver may use for example rtems_timecounter_tick_simple()
+ * instead of the default.
+ */
+#ifndef Clock_driver_timecounter_tick
+  #ifdef CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+    #define Clock_driver_timecounter_tick() rtems_clock_tick()
+  #else
+    #define Clock_driver_timecounter_tick() rtems_timecounter_tick()
+  #endif
+#endif
+
 /**
  * @brief ISRs until next clock tick
  */
@@ -79,7 +95,7 @@ rtems_isr Clock_isr(
 
   #if CLOCK_DRIVER_USE_FAST_IDLE
     do {
-      rtems_clock_tick();
+      Clock_driver_timecounter_tick();
     } while (
       _Thread_Heir == _Thread_Executing
         && _Thread_Executing->Start.entry_point
@@ -101,7 +117,7 @@ rtems_isr Clock_isr(
        *  The driver is multiple ISRs per clock tick.
        */
       if ( !Clock_driver_isrs ) {
-        rtems_clock_tick();
+        Clock_driver_timecounter_tick();
 
         Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
       }
@@ -110,7 +126,7 @@ rtems_isr Clock_isr(
       /*
        *  The driver is one ISR per clock tick.
        */
-      rtems_clock_tick();
+      Clock_driver_timecounter_tick();
     #endif
   #endif
 }
@@ -160,12 +176,6 @@ rtems_device_driver Clock_initialize(
   (void) Old_ticker;
   Clock_driver_support_install_isr( Clock_isr, Old_ticker );
 
-  #if defined(Clock_driver_nanoseconds_since_last_tick)
-    rtems_clock_set_nanoseconds_extension(
-      Clock_driver_nanoseconds_since_last_tick
-    );
-  #endif
-
   /*
    *  Now initialize the hardware that is the source of the tick ISR.
    */
diff --git a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
index 2afe770..7a38cf0 100644
--- a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c
@@ -25,6 +25,7 @@
 #include <bsp.h>
 #include <bspopts.h>
 #include <rtems/counter.h>
+#include <rtems/timecounter.h>
 
 #if SIMSPARC_FAST_IDLE==1
 #define CLOCK_DRIVER_USE_FAST_IDLE 1
@@ -44,24 +45,69 @@
 
 extern int CLOCK_SPEED;
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
+static rtems_timecounter_simple erc32_tc;
+
+static uint32_t erc32_tc_get( rtems_timecounter_simple *tc )
 {
+  return ERC32_MEC.Real_Time_Clock_Counter;
+}
+
+static bool erc32_tc_is_pending( rtems_timecounter_simple *tc )
+{
+  return ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK );
+}
+
+static uint32_t erc32_tc_get_timecount( struct timecounter *tc )
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    erc32_tc_get,
+    erc32_tc_is_pending
+  );
+}
+
+#if CLOCK_DRIVER_USE_FAST_IDLE == 1
+extern volatile uint32_t Clock_driver_ticks;
+
+static uint32_t erc32_tc_get_fast_idle( rtems_timecounter_simple *tc )
+{
+  static uint32_t last;
+  uint32_t current;
   uint32_t clicks;
-  uint32_t usecs;
 
-  clicks = ERC32_MEC.Real_Time_Clock_Counter;
+  current = Clock_driver_ticks;
 
-  if ( ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK ) ) {
-    clicks = ERC32_MEC.Real_Time_Clock_Counter;
-    usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks);
+  if ( last != current ) {
+    last = current;
+    clicks = erc32_tc_get( tc );
   } else {
-    usecs = (rtems_configuration_get_microseconds_per_tick() - clicks);
+    ERC32_MEC.Real_Time_Clock_Counter = tc->real_interval;
+    ERC32_MEC_Set_Real_Time_Clock_Timer_Control(
+      ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
+      ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER
+    );
+    ERC32_MEC_Set_Real_Time_Clock_Timer_Control(
+      ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
+      ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO
+    );
+    clicks = tc->real_interval;
   }
-  return usecs * 1000;
+
+  return clicks;
 }
+#endif
 
-#define Clock_driver_nanoseconds_since_last_tick \
-  bsp_clock_nanoseconds_since_last_tick
+static void erc32_tc_tick( void )
+{
+  rtems_timecounter_simple_downcounter_tick(
+    &erc32_tc,
+#if CLOCK_DRIVER_USE_FAST_IDLE == 1
+    erc32_tc_get_fast_idle
+#else
+    erc32_tc_get
+#endif
+  );
+}
 
 static CPU_Counter_ticks erc32_counter_difference(
   CPU_Counter_ticks second,
@@ -75,6 +121,7 @@ static CPU_Counter_ticks erc32_counter_difference(
 
 #define Clock_driver_support_initialize_hardware() \
   do { \
+    uint32_t frequency = 1000000; \
     /* approximately 1 us per countdown */ \
     ERC32_MEC.Real_Time_Clock_Scalar  = CLOCK_SPEED - 1; \
     ERC32_MEC.Real_Time_Clock_Counter = \
@@ -89,14 +136,22 @@ static CPU_Counter_ticks erc32_counter_difference(
     ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \
         ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \
         ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO \
+    );  \
+    rtems_timecounter_simple_install( \
+        &erc32_tc, \
+        frequency, \
+        rtems_configuration_get_microseconds_per_tick(), \
+        erc32_tc_get_timecount \
     ); \
     _SPARC_Counter_initialize( \
       &ERC32_MEC.Real_Time_Clock_Counter, \
       erc32_counter_difference \
     ); \
-    rtems_counter_initialize_converter(1000000); \
+    rtems_counter_initialize_converter( frequency ); \
   } while (0)
 
+#define Clock_driver_timecounter_tick() erc32_tc_tick()
+
 #define Clock_driver_support_shutdown_hardware() \
   do { \
     ERC32_Mask_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK ); \
diff --git a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
index ab4efa0..3dd68e0 100644
--- a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c
@@ -24,11 +24,38 @@
 
 #include <bsp.h>
 #include <bspopts.h>
+#include <rtems/timecounter.h>
 
 #if SIMSPARC_FAST_IDLE==1
 #define CLOCK_DRIVER_USE_FAST_IDLE 1
 #endif
 
+static rtems_timecounter_simple leon2_tc;
+
+static uint32_t leon2_tc_get( rtems_timecounter_simple *tc )
+{
+  return LEON_REG.Timer_Counter_1;
+}
+
+static bool leon2_tc_is_pending( rtems_timecounter_simple *tc )
+{
+  return LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 );
+}
+
+static uint32_t leon2_tc_get_timecount( struct timecounter *tc )
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    leon2_tc_get,
+    leon2_tc_is_pending
+  );
+}
+
+static void leon2_tc_tick( void )
+{
+  rtems_timecounter_simple_downcounter_tick( &leon2_tc, leon2_tc_get );
+}
+
 /*
  *  The Real Time Clock Counter Timer uses this trap type.
  */
@@ -54,6 +81,12 @@ extern int CLOCK_SPEED;
         LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO | \
         LEON_REG_TIMER_COUNTER_LOAD_COUNTER  \
     ); \
+    rtems_timecounter_simple_install( \
+      &leon2_tc, \
+      1000000, \
+      rtems_configuration_get_microseconds_per_tick(), \
+      leon2_tc_get_timecount \
+    ); \
   } while (0)
 
 #define Clock_driver_support_shutdown_hardware() \
@@ -62,23 +95,6 @@ extern int CLOCK_SPEED;
     LEON_REG.Timer_Control_1 = 0; \
   } while (0)
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-  uint32_t clicks;
-  uint32_t usecs;
-
-  clicks = LEON_REG.Timer_Counter_1;
-
-  if ( LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 ) ) {
-    clicks = LEON_REG.Timer_Counter_1;
-    usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks);
-  } else {
-    usecs = (rtems_configuration_get_microseconds_per_tick() - clicks);
-  }
-  return usecs * 1000;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-    bsp_clock_nanoseconds_since_last_tick
+#define Clock_driver_timecounter_tick() leon2_tc_tick()
 
 #include "../../../shared/clockdrv_shell.h"
diff --git a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
index ad22616..b82b457 100644
--- a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
@@ -24,6 +24,7 @@
 #include <rtems/rtems/intr.h>
 #include <ambapp.h>
 #include <rtems/score/profiling.h>
+#include <rtems/timecounter.h>
 
 /* The LEON3 BSP Timer driver can rely on the Driver Manager if the
  * DrvMgr is initialized during startup. Otherwise the classic driver
@@ -40,6 +41,43 @@
 /* LEON3 Timer system interrupt number */
 static int clkirq;
 
+static bool leon3_tc_use_irqmp;
+
+static rtems_timecounter_simple leon3_tc;
+
+static uint32_t leon3_tc_get(rtems_timecounter_simple *tc)
+{
+  return LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value;
+}
+
+static bool leon3_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return LEON_Is_interrupt_pending(clkirq);
+}
+
+static uint32_t leon3_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_downcounter_get(
+    tc,
+    leon3_tc_get,
+    leon3_tc_is_pending
+  );
+}
+
+static uint32_t leon3_tc_get_timecount_irqmp(struct timecounter *tc)
+{
+  return LEON3_IrqCtrl_Regs->timestamp[0].counter;
+}
+
+static void leon3_tc_tick(void)
+{
+  if (leon3_tc_use_irqmp) {
+    rtems_timecounter_tick();
+  } else {
+    rtems_timecounter_simple_downcounter_tick(&leon3_tc, leon3_tc_get);
+  }
+}
+
 static void leon3_clock_profiling_interrupt_delay(void)
 {
 #ifdef RTEMS_PROFILING
@@ -112,15 +150,36 @@ static void bsp_clock_handler_install(rtems_isr *new)
   }
 }
 
+static void leon3_clock_initialize(void)
+{
+  volatile struct irqmp_timestamp_regs *irqmp_ts =
+    &LEON3_IrqCtrl_Regs->timestamp[0];
+
+  LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].reload =
+    rtems_configuration_get_microseconds_per_tick() - 1;
+  LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl =
+    GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS |
+      GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE;
+
+  if (leon3_irqmp_has_timestamp(irqmp_ts)) {
+    leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_irqmp;
+    leon3_tc.tc.tc_counter_mask = 0xffffffff;
+    leon3_tc.tc.tc_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev);
+    leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+    leon3_tc_use_irqmp = true;
+    rtems_timecounter_install(&leon3_tc.tc);
+  } else {
+    rtems_timecounter_simple_install(
+      &leon3_tc,
+      LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER,
+      rtems_configuration_get_microseconds_per_tick(),
+      leon3_tc_get_timecount
+    );
+  }
+}
+
 #define Clock_driver_support_initialize_hardware() \
-  do { \
-    LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].reload = \
-      rtems_configuration_get_microseconds_per_tick() - 1; \
-    \
-    LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = \
-      GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS | \
-        GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE; \
-  } while (0)
+  leon3_clock_initialize()
 
 #define Clock_driver_support_shutdown_hardware() \
   do { \
@@ -128,27 +187,7 @@ static void bsp_clock_handler_install(rtems_isr *new)
     LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = 0; \
   } while (0)
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-  uint32_t clicks;
-  uint32_t usecs;
-
-  if ( !LEON3_Timer_Regs )
-    return 0;
-
-  clicks = LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value;
-
-  if ( LEON_Is_interrupt_pending( clkirq ) ) {
-    clicks = LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value;
-    usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks);
-  } else {
-    usecs = (rtems_configuration_get_microseconds_per_tick() - clicks);
-  }
-  return usecs * 1000;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-        bsp_clock_nanoseconds_since_last_tick
+#define Clock_driver_timecounter_tick() leon3_tc_tick()
 
 #include "../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c b/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c
index a3f9450..ff0464c 100644
--- a/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c
@@ -114,5 +114,7 @@ static void Clock_driver_support_initialize_hardware(void)
     \
   } while ( 0 )
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c b/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c
index 16cf145..42b85f3 100644
--- a/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c
+++ b/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c
@@ -22,8 +22,6 @@
 #include <at91rm9200.h>
 #include <at91rm9200_pmc.h>
 
-static unsigned long st_pimr_reload;
-
 /**
  * Enables clock interrupt.
  *
@@ -77,17 +75,16 @@ rtems_irq_connect_data clock_isr_data = {
       BSP_install_rtems_irq_handler(&clock_isr_data);  \
   } while(0)
 
-uint16_t st_pimr_value;
 static void Clock_driver_support_initialize_hardware(void)
 {
   uint32_t st_str;
   int slck;
+  unsigned long value;
 
   /* the system timer is driven from SLCK */
   slck = at91rm9200_get_slck();
-  st_pimr_value = (((rtems_configuration_get_microseconds_per_tick() * slck) +
+  value = (((rtems_configuration_get_microseconds_per_tick() * slck) +
                       (1000000/2))/ 1000000);
-  st_pimr_reload = st_pimr_value;
 
   /* read the status to clear the int */
   st_str = ST_REG(ST_SR);
@@ -97,21 +94,9 @@ static void Clock_driver_support_initialize_hardware(void)
   AIC_SMR_REG(AIC_SMR_SYSIRQ) = AIC_SMR_PRIOR(0x7);
 
   /* set the timer value */
-  ST_REG(ST_PIMR) = st_pimr_reload;
+  ST_REG(ST_PIMR) = value;
 }
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-  uint16_t slck_counts;
-
-  slck_counts = st_pimr_value - st_pimr_reload;
-  return (rtems_configuration_get_microseconds_per_tick() * slck_counts * 1000)
-     / st_pimr_value;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-  bsp_clock_nanoseconds_since_last_tick
-
 #define Clock_driver_support_at_tick() \
   do { \
     uint32_t st_str; \
@@ -126,4 +111,6 @@ static void Clock_driver_support_shutdown_hardware( void )
   BSP_remove_rtems_irq_handler(&clock_isr_data);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../../libbsp/shared/clockdrv_shell.h"
diff --git a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
index 02f5b8c..e75fed8 100644
--- a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
+++ b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c
@@ -17,12 +17,39 @@
 #include <bsp/irq.h>
 #include <lpc22xx.h>
 #include <rtems/bspIo.h>  /* for printk */
+#include <rtems/timecounter.h>
 
 void Clock_isr(rtems_irq_hdl_param arg);
 static void clock_isr_on(const rtems_irq_connect_data *unused);
 static void clock_isr_off(const rtems_irq_connect_data *unused);
 static int clock_isr_is_on(const rtems_irq_connect_data *irq);
 
+static rtems_timecounter_simple lpc22xx_tc;
+
+static uint32_t lpc22xx_tc_get(rtems_timecounter_simple *tc)
+{
+  return T0TC;
+}
+
+static bool lpc22xx_tc_is_pending(rtems_timecounter_simple *tc)
+{
+  return (T0IR & 0x1) != 0;
+}
+
+static uint32_t lpc22xx_tc_get_timecount(struct timecounter *tc)
+{
+  return rtems_timecounter_simple_upcounter_get(
+    tc,
+    lpc22xx_tc_get,
+    lpc22xx_tc_is_pending
+  );
+}
+
+static void lpc22xx_tc_tick(void)
+{
+  rtems_timecounter_simple_upcounter_tick(&lpc22xx_tc, lpc22xx_tc_get);
+}
+
 /* Replace the first value with the clock's interrupt name. */
 rtems_irq_connect_data clock_isr_data = {
   .name   = LPC22xx_INTERRUPT_TIMER0,
@@ -74,9 +101,10 @@ rtems_irq_connect_data clock_isr_data = {
  */
 #define Clock_driver_support_initialize_hardware() \
   do { \
+    uint32_t mask; \
     /* disable and clear timer 0, set to  */ \
     T0TCR &= 0;                              \
-    /* TC is incrementet on every pclk.*/    \
+    /* TC is incremented on every pclk.*/    \
     T0PC   = 0;                              \
     /* initialize the timer period and prescaler */  \
     T0MR0  = ((LPC22xx_Fpclk/1000 *          \
@@ -89,6 +117,13 @@ rtems_irq_connect_data clock_isr_data = {
     T0TCR = 1;              \
     /* enable interrupt, skyeye will check this*/ \
     T0IR |= 0x01; \
+    /* install timecounter */ \
+    rtems_timecounter_simple_install( \
+      &lpc22xx_tc, \
+      LPC22xx_Fpclk, \
+      T0MR0, \
+      lpc22xx_tc_get_timecount \
+    ); \
   } while (0)
 
 /**
@@ -104,20 +139,6 @@ rtems_irq_connect_data clock_isr_data = {
     BSP_remove_rtems_irq_handler(&clock_isr_data);                  \
   } while (0)
 
-static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
-{
-  uint32_t clicks;
-  uint32_t microseconds;
-
-  clicks = T0TC;  /* T0TC is the 32bit time counter 0 */
-
-  microseconds = (rtems_configuration_get_microseconds_per_tick() - clicks);
-  return microseconds * 1000;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-        bsp_clock_nanoseconds_since_last_tick
-
 /**
  * Enables clock interrupt.
  *
@@ -149,6 +170,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
   return T0IR & 0x01;  /* MR0 mask */
 }
 
+#define Clock_driver_timecounter_tick() lpc22xx_tc_tick()
+
 /* Make sure to include this, and only at the end of the file */
 #include "../../../../libbsp/shared/clockdrv_shell.h"
 
diff --git a/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c b/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c
index 0c3ab5d..d5dc69c 100644
--- a/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c
+++ b/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c
@@ -130,5 +130,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
   return MC9328MXL_TMR1_TCTL & MC9328MXL_TMR_TCTL_IRQEN;
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 /* Make sure to include this, and only at the end of the file */
+
 #include "../../../../libbsp/shared/clockdrv_shell.h"
diff --git a/c/src/lib/libcpu/arm/pxa255/clock/clock.c b/c/src/lib/libcpu/arm/pxa255/clock/clock.c
index 92d9b21..69b6849 100644
--- a/c/src/lib/libcpu/arm/pxa255/clock/clock.c
+++ b/c/src/lib/libcpu/arm/pxa255/clock/clock.c
@@ -116,4 +116,6 @@ static void Clock_driver_support_shutdown_hardware( void )
   BSP_remove_rtems_irq_handler(&clock_isr_data);
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 #include "../../../../libbsp/shared/clockdrv_shell.h"
diff --git a/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c b/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c
index 519d3f8..a92dc60 100644
--- a/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c
+++ b/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c
@@ -28,17 +28,6 @@ rtems_irq_connect_data clock_isr_data = {
 };
 
 /**
- *  Return the nanoseconds since last tick
- */
-static uint32_t clock_driver_get_nanoseconds_since_last_tick(void)
-{
-  return 0;
-}
-
-#define Clock_driver_nanoseconds_since_last_tick \
-  clock_driver_get_nanoseconds_since_last_tick
-
-/**
  * When we get the clock interrupt
  *    - clear the interrupt bit?
  *    - restart the timer?
@@ -74,6 +63,7 @@ static uint32_t clock_driver_get_nanoseconds_since_last_tick(void)
   do { \
         uint32_t cr; \
         uint32_t freq; \
+        uint32_t mask; \
         /* set MUX for Timer4 to 1/16 */ \
         cr=rTCFG1 & 0xFFF0FFFF; \
         rTCFG1=(cr | (3<<16)); \
@@ -131,5 +121,7 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
   return 1;
 }
 
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
 /* Make sure to include this, and only at the end of the file */
 #include "../../../../libbsp/shared/clockdrv_shell.h"
diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c b/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c
index 218828c..4fb9912 100644
--- a/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c
+++ b/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c
@@ -29,6 +29,7 @@
 #include <libcpu/spr.h>
 #include <rtems/bspIo.h>                /* for printk() */
 #include <libcpu/powerpc-utility.h>
+#include <rtems/timecounter.h>
 
 #include <bspopts.h>   /* for CLOCK_DRIVER_USE_FAST_IDLE */
 
@@ -48,11 +49,12 @@ volatile uint32_t   Clock_driver_ticks;
  */
 static uint32_t   Clock_Decrementer_value;
 
-/*
- *  This is the value by which elapsed count down timer ticks are multiplied to
- *  give an elapsed duration in nanoseconds, left-shifted by 32 bits
- */
-static uint64_t   Clock_Decrementer_reference;
+static struct timecounter Clock_TC;
+
+static uint32_t Clock_Get_timecount(struct timecounter *tc)
+{
+  return ppc_time_base();
+}
 
 void clockOff(void* unused)
 {
@@ -95,15 +97,14 @@ static void clockHandler(void)
 {
   #if (CLOCK_DRIVER_USE_FAST_IDLE == 1)
     do {
-      rtems_clock_tick();
+      rtems_timecounter_tick();
     } while (
       _Thread_Heir == _Thread_Executing
         && _Thread_Executing->Start.entry_point
           == (Thread_Entry) rtems_configuration_get_idle_task()
     );
-
   #else
-    rtems_clock_tick();
+    rtems_timecounter_tick();
   #endif
 }
 
@@ -141,7 +142,6 @@ void clockIsr(void *unused)
     rtems_interrupt_enable(flags);
 
     Clock_driver_ticks += 1;
-
     /*
      *  Real Time Clock counter/timer is set to automatically reload.
      */
@@ -187,7 +187,6 @@ int clockIsOn(void* unused)
   return 0;
 }
 
-
 /*
  *  Clock_exit
  *
@@ -199,53 +198,6 @@ void Clock_exit( void )
   (void) BSP_disconnect_clock_handler ();
 }
 
-static uint32_t Clock_driver_nanoseconds_since_last_tick(void)
-{
-  uint32_t clicks, tmp;
-
-  PPC_Get_decrementer( clicks );
-
-  /*
-   * Multiply by 1000 here separately from below so we do not overflow
-   * and get a negative value.
-   */
-  tmp = (Clock_Decrementer_value - clicks) * 1000;
-  tmp /= (BSP_bus_frequency/BSP_time_base_divisor);
-
-  return tmp * 1000;
-}
-
-static uint32_t Clock_driver_nanoseconds_since_last_tick_bookE(void)
-{
-  uint32_t clicks;
-  uint64_t c;
-
-  PPC_Get_decrementer( clicks );
-  c = Clock_Decrementer_value - clicks;
-
-  /*
-   * Check whether a clock tick interrupt is pending and hence that the
-   * decrementer's wrapped. If it has, we'll compensate by returning a time one
-   * tick period longer.
-   *
-   * We have to check interrupt status after reading the decrementer. If we
-   * don't, we may miss an interrupt and read a wrapped decrementer value
-   * without compensating for it
-   */
-  if ( _read_BOOKE_TSR() & BOOKE_TSR_DIS )
-  {
-    /*
-     * Re-read the decrementer: The tick interrupt may have been
-     * generated and the decrementer wrapped during the time since we
-     * last read it and the time we checked the interrupt status
-     */
-    PPC_Get_decrementer( clicks );
-    c = (Clock_Decrementer_value - clicks) + Clock_Decrementer_value;
-  }
-
-  return (uint32_t)((c * Clock_Decrementer_reference) >> 32);
-}
-
 /*
  *  Clock_initialize
  *
@@ -262,9 +214,6 @@ rtems_device_driver Clock_initialize(
   Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
             rtems_configuration_get_milliseconds_per_tick();
 
-  Clock_Decrementer_reference = ((uint64_t)1000000U<<32)/
-            (BSP_bus_frequency/BSP_time_base_divisor);
-
   /* set the decrementer now, prior to installing the handler
    * so no interrupts will happen in a while.
    */
@@ -283,24 +232,14 @@ rtems_device_driver Clock_initialize(
       _write_BOOKE_TCR(tcr);
 
     rtems_interrupt_enable(l);
-
-    /*
-     *  Set the nanoseconds since last tick handler
-     */
-    rtems_clock_set_nanoseconds_extension(
-      Clock_driver_nanoseconds_since_last_tick_bookE
-    );
-  }
-  else
-  {
-    /*
-     *  Set the nanoseconds since last tick handler
-     */
-    rtems_clock_set_nanoseconds_extension(
-      Clock_driver_nanoseconds_since_last_tick
-    );
   }
 
+  Clock_TC.tc_get_timecount = Clock_Get_timecount;
+  Clock_TC.tc_counter_mask = 0xffffffff;
+  Clock_TC.tc_frequency = (1000 * BSP_bus_frequency) / BSP_time_base_divisor;
+  Clock_TC.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(&Clock_TC);
+
   /*
    * If a decrementer exception was pending, it is cleared by
    * executing the default (nop) handler at this point;
-- 
1.8.4.5




More information about the devel mailing list