summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386
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/i386
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/i386')
-rw-r--r--c/src/lib/libbsp/i386/pc386/clock/ckinit.c125
1 files changed, 22 insertions, 103 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c
index 2782252680..44a35bc6c1 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;
}